diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 4798c37853..0c9bf10954 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -22,6 +22,7 @@ e4d38681df23ccca0ae29581a45f8362574e0630 a9d96219902cf609636886c7073a84407f450d9a d866510188d26d51bcd6d37239283db690af7e82 0dcd0a3c1abcaffe5529f8d79a6bc34734b195c7 +e096358c832ab292ddfd22dd5878826c7c788968 # Ran SystemTests and python/ctsm through black python formatter 5364ad66eaceb55dde2d3d598fe4ce37ac83a93c 8056ae649c1b37f5e10aaaac79005d6e3a8b2380 @@ -32,3 +33,13 @@ d866510188d26d51bcd6d37239283db690af7e82 6fccf682eaf718615407d9bacdd3903b8786a03d 2500534eb0a83cc3aff94b30fb62e915054030bf 78d05967c2b027dc9776a884716597db6ef7f57c +a0d014fae9550dd9ffbc934abd29ef16176f8208 +c7b7ca1d94ac19abb9ecea9fb5b712ddbdd6645d +b565b55ce7a9f8d812a573d716a5fd3d78cfea81 +fdf72cd011e2ba318987a1e100efc5a1847c9d04 +de9a30bfbbec36f9dcacc4380005ab596da47af4 +cda0cf1412212e6f4363e6e8eb39f74c944b454d +aa04d1f7d86cc2503b98b7e2b2d84dbfff6c316b +6c6f57e948bfa31e60b383536cc21663fedb8b70 +9660667b1267dcd4150889f5f39db540158be74a +665cf86102e09b4c4c5a140700676dca23bc55a9 diff --git a/.gitignore b/.gitignore index ec2a3b17f6..1da8072fed 100644 --- a/.gitignore +++ b/.gitignore @@ -79,32 +79,31 @@ test_driver_*.sh # mksurfdata output surfdata_*.log -surfdata_*.namelist -landuse.timeseries_*.namelist +*.namelist +mksurfdata.o* landuse.timeseries_*.log landuse_timeseries_*.txt ctsm.input_data_list ctsm.input_data_list.previous *.stdout.txt.o* +/tools/mksurfdata_esmf/PET* +/tools/mksurfdata_esmf/job_name.o* +/tools/mksurfdata_esmf/mksurfdata_in +/tools/mksurfdata_esmf/surfdata_*.nc +/tools/mksurfdata_esmf/landuse.timeseries_*.nc +/tools/mksurfdata_esmf/mksurfdata_jobscript_multi.sh +/tools/mksurfdata_esmf/mksurfdata_jobscript_single.sh +/tools/mksurfdata_esmf/pio_iotype.txt +/tools/mksurfdata_esmf/*.sh +/tools/mksurfdata_esmf/tool_bld +/tools/mksurfdata_esmf/pio_iotype.txt # mksurfdata unit tests unit_test_build # Tools executables -/tools/mksurfdata_map/mksurfdata_map /tools/mkprocdata_map/mkprocdata_map -# mksurfdata output files -/tools/mksurfdata_map/surfdata_*.nc -/tools/mksurfdata_map/landuse.timeseries_*.nc - -# mkmapdata output files -/tools/mkmapdata/PET*.RegridWeightGen.Log -/tools/mkmapdata/regrid.*.out -/tools/mkmapdata/regrid.*.err -/tools/mkmapdata/regrid.o* -/tools/mkmapdata/map*.nc - # run_neon output directories /tools/site_and_regional/listing.csv /tools/site_and_regional/????/ diff --git a/Externals_CLM.cfg b/Externals_CLM.cfg index 69d13ca73b..378992c777 100644 --- a/Externals_CLM.cfg +++ b/Externals_CLM.cfg @@ -1,7 +1,7 @@ [fates] local_path = src/fates protocol = git -repo_url = https://github.com/rgknox/fates +repo_url = https://github.com/NGEET/fates tag = sci.1.72.2_api.34.0.0 required = True diff --git a/README b/README index b2ac1eec4e..18cc2b1458 100644 --- a/README +++ b/README @@ -1,6 +1,6 @@ -$CTSMROOT/README 06/08/2018 +$CTSMROOT/README 04/19/2023 -Community Terrestrial Systems Model (CTSM) science version 5.1 series -- source code, tools, +Community Terrestrial Systems Model (CTSM) science version 5.2 series -- source code, tools, offline-build and test scripts. This gives you everything you need to run CTSM with CESM with the CMEPS driver and CDEPS data models to provide CRU NCEP or GSWP3 forcing data in place of a modeled atmosphere. @@ -35,40 +35,47 @@ this checkout. For a CESM checkout $CIMEROOT will be the "cime" directory beneath the top level directory. For a CTSM checkout $CIMEROOT will be $CTSMROOT/cime. +IMPORTANT NOTE ABOUT (deprecated) + +Anything marked with (deprecated) is something is going to be removed in a future update. +Often this means it will be replaced with something else. + + General directory structure ($CTSMROOT): doc --------------- Documentation of CTSM. -bld --------------- Template, configure and build-namelist scripts for clm. +bld --------------- build-namelist scripts for CTSM. src --------------- CTSM Source code. lilac ------------- Lightweight Infrastructure for Land-Atmosphere Coupling (for coupling to a host atmosphere model) -test -------------- CTSM Testing scripts for CTSM offline tools. +test -------------- CTSM Testing scripts for CTSM offline tools (deprecated) tools ------------- CTSM Offline tools to prepare input datasets and process output. cime_config ------- Configuration files of cime for compsets and CTSM settings -manage_externals -- Script to manage the external source directories +manage_externals -- Script to manage the external source directories (deprecated) py_env_create ----- Script to setup the python environment for CTSM python tools using conda -python ------------ Some python modules mostly for use by run_sys_tests (but could be used elsewhere l +python ------------ Python modules used in tools and testing and automated checking of ALL CTSM python scirpts Directory structure only for a CTSM checkout: components -------- Other active sub-components needed for CTSM to run (river routing and land-ice models) -libraries --------- CESM libraries: MCT (Model Coupling Toolkit) and PIO +libraries --------- CESM libraries: MCT (Model Coupling Toolkit) and PIO (deprecated) share ------------- CESM shared code +ccs_config -------- CIME configure files (for grids, compsets, and machines) for CESM cime/scripts --------------- cesm/cime driver scripts components/cmeps -------------------- CESM top level driver (for NUOPC driver [which is the default]) source code. components/cdeps -------------------- CESM top level data model shared code (for NUOPC driver). -cime/src/externals ------------------ CESM external utility codes (genf90) components/cism --------------------- CESM Community land Ice Sheet Model. components/mosart ------------------- Model for Scale Adaptive River Transport components/rtm ---------------------- CESM River Transport Model. -components/cpl7 --------------------- CESM top level driver for MCT driver (being deprecated) +components/cpl7 --------------------- CESM top level driver for MCT driver (deprecated will be removed) Top level documentation ($CTSMROOT): README ------------------- This file +README.md ---------------- File that displays on github under https::/github.com/ESCOMP/CTSM.git README.rst --------------- File that displays under the project in github -README_EXTERNALS.rst ----- Information on how to work with subversion externals for clm +README_EXTERNALS.rst ----- Information on how to work with manage_externals for CTSM (deprecated) CODE_OF_CONDUCT.md ------- Code of Conduct for how to work with each other on the CTSM project Copyright ---------------- CESM Copyright file doc/UpdateChangeLog.pl --- Script to add documentation on a tag to the @@ -92,7 +99,7 @@ bld/namelist_files/namelist_defaults_ctsm.xml ----- Default values Important files in main directories (under $CTSMROOT): ============================================================================================= -Externals.cfg --------------- File for management of the main high level externals +Externals.cfg --------------- File for management of the main high level external (deprecated) Externals_CLM.cfg ----------- File for management of the CTSM specific externals (i.e. FATES) run_sys_tests --------------- Python script to send the standard CTSM testing off (submits @@ -103,18 +110,15 @@ parse_cime.cs.status -------- Script to parse test status files cs.status.* crea (can be used along with run_sys_tests) doc/Quickstart.GUIDE -------- Quick guide to using NUOPC scripts. doc/IMPORTANT_NOTES --------- Some important notes about this version of - clm, configuration modes and namelist items + CTSM, configuration modes and namelist items that are not validated or functional. doc/ChangeLog --------------- Detailed list of changes for each model version. doc/ChangeSum --------------- Summary one-line list of changes for each model version. -doc/README ------------------ Documentation similar to this file doc/UsersGuide -------------- CTSM Users Guide doc/IMPORTANT_NOTES --------- Some important notes on caveats for some configurations/namelist items -bld/README ------------------ Description of how to use the configure and - build-namelist scripts. -bld/configure --------------- Script to prepare CTSM to be built. +bld/README ------------------ Description of how to use the build-namelist scripts. bld/build-namelist ---------- Script to build CTSM namelists. cime_config/buildnml ------------- Build the CTSM namelist for CIME @@ -127,23 +131,15 @@ cime_config/testdefs ------------- Directory for specification of CTSM testing cime_config/testdefs/ExpectedTestFails.xml -- List of tests that are expected to fail cime_config/usermods_dirs -------- Directories of sets of user-modification subdirs (These are directories that add specific user modifications to - simulations created using "cime/scripts/create_newcase --user-mods-dir". - Current sub directories are for various CMIP6 configurations) - -test/tools/test_driver.sh -- Script for general software testing of - CTSM's offline tools. + simulations created using "cime/scripts/create_newcase --user-mods-dir".) -tools/mksurfdata_map ---------- Directory to build program to create surface dataset +tools/mksurfdata_esmf --------- Directory to build program to create surface dataset at any resolution. -tools/mkdatadomain ------------ Directory to build program to create datm7 or docn7 - domain files from clm files. tools/mkprocdata_map ---------- Process history data from unstructed grids to a gridded format. -tools/mkmapgrids -------------- NCL script to create a SCRIP grid file for a regular lat/lon grid -tools/ncl_scripts ------------ Directory of NCL and perl scripts to do various - tasks. Most notably to plot perturbation error growth - testing and to extract regional information from - global datasets for single-point/regional simulations. +tools/mkmapgrids -------------- NCL script to create a SCRIP grid file for a regular lat/lon grid (deprecated) +tools/crop_calendars ---------- Tools to process and process and create crop calendar datasets for CTSM +tools/modify_input_files ------ Script to modify existing CTSM input datasets in standard ways tools/site_and_regional ------- Scripts to create input datasets for single site and regional cases, primarily by modifying existing global datasets tools/contrib ----------------- Miscellansous useful scripts for pre and post processing @@ -166,6 +162,7 @@ scr/fates --------- FATES model and sub-directories Functionally Assembled Terrestrial Ecosystem Simulator (FATES) Experimental Ecosystem Demography model src/utils --------- Utility codes +src/self_tests ---- Internal testing (unit tests run as a part of a CTSM simulation) src/unit_test_shr - Unit test shared modules for unit testing src/unit_test_stubs Unit test stubs that replicate CTSM code simpler @@ -175,11 +172,10 @@ src/unit_test_stubs Unit test stubs that replicate CTSM code simpler cd $CIMEROOT/scripts ./create_newcase # get help on how to run create_newcase - ./create_newcase --case testI --res f19_g17_gl4 --compset I2000Clm50BgcCrop + ./create_newcase --case testI --res f19_g17_gl4 --compset I2000Clm60BgcCrop # create new "I" case for default machine at 1.9x2.5_gx1v7 - # with 4km greenland ice sheetres resolution - # "I2000Clm50BgcCrop" case is clm5_0 active, datm8, and inactive ice/ocn - # With no-evolve ice-sheet, and MOSART for river-routing + # "I2000Clm60BgcCrop" case is clm6_0 physics, CDEPS, and inactive ice/ocn/glc + # and MOSART for river-routing cd testI ./case.setup # create the $CASE.run file ./case.build # build model and create namelists diff --git a/README.CHECKLIST.new_case b/README.CHECKLIST.new_case index d3b37bc7c3..71ba4a8284 100644 --- a/README.CHECKLIST.new_case +++ b/README.CHECKLIST.new_case @@ -22,6 +22,8 @@ General Checklist to always do: (./xmlquery LND_TUNING_MODE) - For an "I compset" make sure you are running over the right forcing years (usually ./xmlquery -p DATM_YR) + - Again for an "I compset" make sure the DATM streams are operating over the right years + (look at the CaseDocs/datm.streams.xml file) - First and align year for streams should be the start year of a historical simulation (./xmlquery RUN_STARTDATE) (grep stream_year_first CaseDocs/lnd_in; grep model_year_align CaseDocs/lnd_in) diff --git a/README.NUOPC_driver.md b/README.NUOPC_driver.md index 578ba4aa8d..ba0b70c2c0 100644 --- a/README.NUOPC_driver.md +++ b/README.NUOPC_driver.md @@ -41,15 +41,10 @@ nuopc.runseq is a text file that determines how the driver operates. You can cha by having an updated copy in your case directory. -## What if I want to use the previous MCT driver? - -The MCT driver will be available for sometime going forward, but -new development won't go into it, and it will eventually be removed. -But, if you have to... -Use the "--driver mct" command line option to create_newcase -You can set COMP_INTERFACE in a case as well, but it won't create it with everything needed -so we recommend setting up a case from scratch. +## What if I want to use the MCT driver? +The MCT driver is now deprecated, and will be removed. So at this point we don't +suggest using it anymore. For more notes see: diff --git a/README.md b/README.md index 9de22e3663..045af9f6a1 100644 --- a/README.md +++ b/README.md @@ -50,12 +50,18 @@ Software engineering team: - [Ryan Knox](https://github.com/rgknox) Science team: -- [Dave Lawrence](https://github.com/dlawrenncar) - [Will Wieder](https://github.com/wwieder) +- [Dave Lawrence](https://github.com/dlawrenncar) - [Danica Lombardozzi](https://github.com/danicalombardozzi) - [Keith Oleson](https://github.com/olyson) - [Sean Swenson](https://github.com/swensosc) -- [Jackie Shuman](https://github.com/jkshuman) - [Peter Lawrence](https://github.com/lawrencepj1) -- [Rosie Fisher](https://github.com/rosiealice) - Gordon Bonan + +FATES Project: +- https://github.com/NGEET/fates?tab=readme-ov-file + +Perturbed Parameter Experiment (PPE) Science team: +- [Katie Dagon] (https://github.com/katiedagon) +- [Daniel Kennedy] (https://github.com/djk2120) +- [Linnea Hawkins] (https://github.com/linniahawkins) \ No newline at end of file diff --git a/README_EXTERNALS.rst b/README_EXTERNALS.rst index 47632f3111..ed7a068991 100644 --- a/README_EXTERNALS.rst +++ b/README_EXTERNALS.rst @@ -1,6 +1,11 @@ Obtaining the full model code and associated scripting infrastructure ===================================================================== +[!CAUTION] +This is deprecated and will be replaced with git submodules. See +https://github.com/ESCOMP/CTSM/pull/2443 + + CTSM is released via GitHub. You will need some familiarity with git in order to modify the code and commit these changes. However, to simply checkout and run the code, no git knowledge is required other than what is documented in the following steps. diff --git a/bld/CLMBuildNamelist.pm b/bld/CLMBuildNamelist.pm index fd8def8845..eb34ac916f 100755 --- a/bld/CLMBuildNamelist.pm +++ b/bld/CLMBuildNamelist.pm @@ -1968,9 +1968,12 @@ sub setup_logic_irrigate { 'use_crop'=>$nl_flags->{'use_crop'}, 'use_cndv'=>$nl_flags->{'use_cndv'}, 'sim_year'=>$nl_flags->{'sim_year'}, 'sim_year_range'=>$nl_flags->{'sim_year_range'}, ); if ( &value_is_true($nl->get_value('irrigate') ) ) { - $nl_flags->{'irrigate'} = ".true." + $nl_flags->{'irrigate'} = ".true."; + if ( $nl_flags->{'sim_year'} eq "PtVg" ) { + $log->fatal_error("irrigate=TRUE does NOT make sense with the Potential Vegetation dataset, leave irrigate=FALSE"); + } } else { - $nl_flags->{'irrigate'} = ".false." + $nl_flags->{'irrigate'} = ".false."; } } @@ -2168,6 +2171,7 @@ sub setup_logic_subgrid { my $var = 'run_zero_weight_urban'; add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $var); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'convert_ocean_to_land'); add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'collapse_urban', 'structure'=>$nl_flags->{'structure'}); add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'n_dom_landunits', @@ -2390,17 +2394,15 @@ sub setup_logic_demand { if ( $item eq "finidat" ) { $log->fatal_error( "Do NOT put findat in the clm_demand list, set the clm_start_type=startup so initial conditions are required"); } - # For landuse.timeseries try with crop and irrigate on first, if found use it, otherwise try with exact settings + # For landuse.timeseries try with crop on first eise try with exact settings # Logic for this is identical for fsurdat if ( $item eq "flanduse_timeseries" ) { - $settings{'irrigate'} = ".true."; $settings{'use_crop'} = ".true."; $settings{'nofail'} = 1; } add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $item, %settings ); if ( $item eq "flanduse_timeseries" ) { $settings{'nofail'} = 0; - $settings{'irrigate'} = $nl_flags->{'irrigate'}; $settings{'use_crop'} = $nl_flags->{'use_crop'}; if ( ! defined($nl->get_value( $item )) ) { add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $item, %settings ); @@ -2443,8 +2445,8 @@ sub setup_logic_surface_dataset { add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $var, 'hgrid'=>$nl_flags->{'res'}, 'ssp_rcp'=>$nl_flags->{'ssp_rcp'}, 'neon'=>$nl_flags->{'neon'}, 'neonsite'=>$nl_flags->{'neonsite'}, - 'sim_year'=>$nl_flags->{'sim_year'}, 'irrigate'=>".true.", 'use_vichydro'=>$nl_flags->{'use_vichydro'}, - 'use_crop'=>".true.", 'glc_nec'=>$nl_flags->{'glc_nec'}, 'use_fates'=>$nl_flags->{'use_fates'}, 'nofail'=>1); + 'sim_year'=>$nl_flags->{'sim_year'}, 'use_vichydro'=>$nl_flags->{'use_vichydro'}, + 'use_crop'=>".true.", 'use_fates'=>$nl_flags->{'use_fates'}, 'nofail'=>1); } # If didn't find the crop version check for the exact match my $fsurdat = $nl->get_value($var); @@ -2454,17 +2456,9 @@ sub setup_logic_surface_dataset { } add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $var, 'hgrid'=>$nl_flags->{'res'}, 'ssp_rcp'=>$nl_flags->{'ssp_rcp'}, 'use_vichydro'=>$nl_flags->{'use_vichydro'}, - 'sim_year'=>$nl_flags->{'sim_year'}, 'irrigate'=>$nl_flags->{'irrigate'}, 'use_fates'=>$nl_flags->{'use_fates'}, - 'neon'=>$nl_flags->{'neon'}, 'neonsite'=>$nl_flags->{'neonsite'}, - 'use_crop'=>$nl_flags->{'use_crop'}, 'glc_nec'=>$nl_flags->{'glc_nec'}, 'nofail'=>1 ); - if ( ! defined($fsurdat) ) { - $log->verbose_message( "Exact match of $var NOT found, searching for version with irrigate true" ); - } - add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $var, - 'hgrid'=>$nl_flags->{'res'}, 'ssp_rcp'=>$nl_flags->{'ssp_rcp'}, 'use_vichydro'=>$nl_flags->{'use_vichydro'}, - 'sim_year'=>$nl_flags->{'sim_year'}, 'irrigate'=>".true.", 'use_fates'=>$nl_flags->{'use_fates'}, + 'sim_year'=>$nl_flags->{'sim_year'}, 'use_fates'=>$nl_flags->{'use_fates'}, 'neon'=>$nl_flags->{'neon'}, 'neonsite'=>$nl_flags->{'neonsite'}, - 'use_crop'=>$nl_flags->{'use_crop'}, 'glc_nec'=>$nl_flags->{'glc_nec'} ); + 'use_crop'=>$nl_flags->{'use_crop'} ); } # # Expand the XML variables for NEON cases so that NEONSITE will be used @@ -2514,11 +2508,17 @@ sub setup_logic_initial_conditions { } my $useinitvar = "use_init_interp"; + my %settings; + my $use_init_interp_default = $nl->get_value($useinitvar); + $settings{$useinitvar} = $use_init_interp_default; + if ( string_is_undef_or_empty( $use_init_interp_default ) ) { + $use_init_interp_default = $defaults->get_value($useinitvar, \%settings); + $settings{$useinitvar} = ".false."; + } if (not defined $finidat ) { my $ic_date = $nl->get_value('start_ymd'); my $st_year = $nl_flags->{'st_year'}; my $nofail = 1; - my %settings; $settings{'hgrid'} = $nl_flags->{'res'}; $settings{'phys'} = $physv->as_string(); $settings{'nofail'} = $nofail; @@ -2555,12 +2555,6 @@ sub setup_logic_initial_conditions { } my $try = 0; my $done = 2; - my $use_init_interp_default = $nl->get_value($useinitvar); - $settings{$useinitvar} = $use_init_interp_default; - if ( string_is_undef_or_empty( $use_init_interp_default ) ) { - $use_init_interp_default = $defaults->get_value($useinitvar, \%settings); - $settings{$useinitvar} = ".false."; - } do { $try++; add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $var, %settings ); @@ -2607,14 +2601,24 @@ SIMYR: foreach my $sim_yr ( @sim_years ) { } } # SIMYR: $settings{'sim_year'} = $closest_sim_year; + # Add options set here to the "$set" variable below... add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $useinitvar, 'use_cndv'=>$nl_flags->{'use_cndv'}, 'phys'=>$physv->as_string(), 'hgrid'=>$nl_flags->{'res'}, 'sim_year'=>$settings{'sim_year'}, 'nofail'=>1, 'lnd_tuning_mode'=>$nl_flags->{'lnd_tuning_mode'}, 'use_fates'=>$nl_flags->{'use_fates'} ); $settings{$useinitvar} = $nl->get_value($useinitvar); if ( ! &value_is_true($nl->get_value($useinitvar) ) ) { - if ( $nl_flags->{'clm_start_type'} =~ /startup/ ) { - $log->fatal_error("clm_start_type is startup so an initial conditions ($var) file is required, but can't find one without $useinitvar being set to true"); + if ( $nl_flags->{'clm_start_type'} =~ /startup/ ) { + my $err_msg = "clm_start_type is startup so an initial conditions ($var) file is required,"; + if ( defined($use_init_interp_default) ) { + $log->fatal_error($err_msg." but can't find one without $useinitvar being set to true, change it to true in your user_nl_clm file in your case"); + } else { + my $set = "Relevent settings: use_cndv = ". $nl_flags->{'use_cndv'} . " phys = " . + $physv->as_string() . " hgrid = " . $nl_flags->{'res'} . " sim_year = " . + $settings{'sim_year'} . " lnd_tuning_mode = " . $nl_flags->{'lnd_tuning_mode'} . + "use_fates = " . $nl_flags->{'use_fates'}; + $log->fatal_error($err_msg." but the default setting of $useinitvar is false, so set both $var to a startup file and $useinitvar==TRUE, or developers should modify the namelist_defaults file".$set); + } } } else { my $stat = add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, "init_interp_attributes", @@ -2623,7 +2627,7 @@ SIMYR: foreach my $sim_yr ( @sim_years ) { 'hgrid'=>$nl_flags->{'res'}, 'use_cn'=>$nl_flags->{'use_cn'}, 'lnd_tuning_mode'=>$nl_flags->{'lnd_tuning_mode'}, 'nofail'=>1 ); if ( $stat ) { - $log->fatal_error("$useinitvar is NOT synchronized with init_interp_attributes"); + $log->fatal_error("$useinitvar is NOT synchronized with init_interp_attributes in the namelist_defaults file, this should be corrected there"); } my $attributes = $nl->get_value("init_interp_attributes"); my $attributes_string = remove_leading_and_trailing_quotes($attributes); @@ -2631,7 +2635,7 @@ SIMYR: foreach my $sim_yr ( @sim_years ) { if ( $pair =~ /^([a-z_]+)=([a-zA-Z._0-9]+)$/ ) { $settings{$1} = $2; } else { - $log->fatal_error("Problem interpreting init_interp_attributes: $pair"); + $log->fatal_error("Problem interpreting init_interp_attributes from the namelist_defaults file: $pair"); } } } @@ -2646,7 +2650,11 @@ SIMYR: foreach my $sim_yr ( @sim_years ) { } $finidat = $nl->get_value($var); if ( &value_is_true($nl->get_value($useinitvar) ) && string_is_undef_or_empty($finidat) ) { - $log->fatal_error("$useinitvar is set BUT $var is NOT, need to set both" ); + if ( ! defined($use_init_interp_default) ) { + $log->fatal_error("You set $useinitvar but a $var file could not be found for this case, try setting $var explicitly, and/or removing the setting for $useinitvar" ); + } else { + $log->fatal_error("$useinitvar is being set for you but a $var was not found, so $useinitvar, init_interp_attributes, and finidat must not be set correctly for this configuration in the namelist_default file" ); + } } } # end initial conditions @@ -2850,6 +2858,13 @@ sub setup_logic_do_transient_lakes { my $var = 'do_transient_lakes'; + # Start by assuming a default value of '.true.'. Then check a number of + # conditions under which do_transient_lakes cannot be true. Under these + # conditions: (1) set default value to '.false.'; (2) make sure that the + # value is indeed false (e.g., that the user didn't try to set it to true). + + my $default_val = ".true."; + # cannot_be_true will be set to a non-empty string in any case where # do_transient_lakes should not be true; if it turns out that # do_transient_lakes IS true in any of these cases, a fatal error will be @@ -2873,7 +2888,7 @@ sub setup_logic_do_transient_lakes { # Note that, if the variable cannot be true, we don't call add_default # - so that we don't clutter up the namelist with variables that don't # matter for this case - add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $var); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $var, val=>$default_val); } # Make sure the value is false when it needs to be false - i.e., that the @@ -2915,6 +2930,13 @@ sub setup_logic_do_transient_urban { my $var = 'do_transient_urban'; + # Start by assuming a default value of '.true.'. Then check a number of + # conditions under which do_transient_urban cannot be true. Under these + # conditions: (1) set default value to '.false.'; (2) make sure that the + # value is indeed false (e.g., that the user didn't try to set it to true). + + my $default_val = ".true."; + # cannot_be_true will be set to a non-empty string in any case where # do_transient_urban should not be true; if it turns out that # do_transient_urban IS true in any of these cases, a fatal error will be @@ -2938,7 +2960,7 @@ sub setup_logic_do_transient_urban { # Note that, if the variable cannot be true, we don't call add_default # - so that we don't clutter up the namelist with variables that don't # matter for this case - add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $var); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $var, val=>$default_val); } # Make sure the value is false when it needs to be false - i.e., that the @@ -4048,7 +4070,6 @@ sub setup_logic_megan { #------------------------------------------------------------------------------- sub setup_logic_soilm_streams { - # prescribed soil moisture streams require clm4_5/clm5_0/clm5_1 my ($opts, $nl_flags, $definition, $defaults, $nl, $physv) = @_; add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'use_soil_moisture_streams'); diff --git a/bld/README b/bld/README index 71c663c268..1e9517b189 100644 --- a/bld/README +++ b/bld/README @@ -19,28 +19,12 @@ build-namelist --- Build the namelists needed env_run.xml --- Sample case runtime environment variables, so build-namelist can run outside of a case directory. ---------- Scripts to query namelist defaults -listDefaultNamelist.pl -- List the files needed, for a list of resolutions, - to run CLM that are currently NOT on your machine. - This file can then be used by - cime/CIME/Tools/check_input_data - to retreive them from the inputdata repository. - Setting up cases with create_newcase also does - this -- but only for the exact configuration - given. This tries to get all the files need - for several different resolutions and configurations - at once. -queryDefaultNamelist.pl - Query default namelist for settings of variables -queryDefaultXML.pm ------ Subroutines needed by queryDefaultNamelist.pl script - - --------- Test scripts directory unit_testers --- Directory of scripts to test scipts in this directory (most notably build-namelist) ---------- XML Files describing namelists in namelist_files namelist_files/namelist_defaults_ctsm.xml --------- List of default values for the ctsm namelist -namelist_files/namelist_defaults_ctsm_tools.xml --- List of default values for the ctsm tools namelist_files/namelist_defaults_overall.xml ------ List of default values for overall settings namelist_files/namelist_defaults_usr_files.xml ---- List of default values for the user-files namelist_files/namelist_definition_ctsm.xml -------- Definition of all namelist items for ctsm @@ -59,7 +43,5 @@ namelist_files/namelist_definition_drv_flds.xml --- Definition of add driver fie ---------- XML helper files namelist_files/LogMessages.pm ---- Perl module to handle log output -namelist_files/checkmapfiles.ncl -- NCL script to check that all of the mapping files are valid -namelist_files/createMapEntry.pl -- Perl script to create a map entry for the namelist_files/history_fields.xsl - Style sheet for history fields as created by script that lists all of the history fields from the source files (../src/main/findHistFields.pl) diff --git a/bld/config_files/clm_phys_vers.pm b/bld/config_files/clm_phys_vers.pm index 3e4de9c610..9ab79ee8b0 100755 --- a/bld/config_files/clm_phys_vers.pm +++ b/bld/config_files/clm_phys_vers.pm @@ -28,7 +28,7 @@ use bigint; #use warnings; #use diagnostics; -my @version_strings = ("clm4_5", "clm5_0", "clm5_1"); +my @version_strings = ("clm4_5", "clm5_0", "clm5_1", "clm6_0"); #------------------------------------------------------------------------------- @@ -88,7 +88,7 @@ if ( ! defined(caller) && $#ARGV == -1 ) { sub testit { print "unit tester\n"; my %lastv; - my @vers_list = ( "clm4_5", "clm5_0", "clm5_1" ); + my @vers_list = ( "clm4_5", "clm5_0", "clm5_1", "clm6_0" ); foreach my $vers ( @vers_list ) { my $phys = config_files::clm_phys_vers->new($vers); isa_ok($phys, "config_files::clm_phys_vers", "created clm_phys_vers object"); diff --git a/bld/config_files/config_definition_ctsm.xml b/bld/config_files/config_definition_ctsm.xml index 06263c6d19..dfe6378f17 100644 --- a/bld/config_files/config_definition_ctsm.xml +++ b/bld/config_files/config_definition_ctsm.xml @@ -5,10 +5,10 @@ -Specifies either clm4_5, clm5_0, or clm5_1 physics +Specifies either clm4_5, clm5_0, clm5_1 (deprecated), or clm6_0 physics new($config_cachefile, '>') or die "can't open file: $config_cachefile"; - print $fh < - - -Specifies clm physics - -EOF - $fh->close(); -} - -#----------------------------------------------------------------------------------------------- - -sub GetListofNeededFiles { -# -# Get list of files that are needed to be copied to disk from the XML file. -# - my $inputopts_ref = shift; - my $settings_ref = shift; - my $files_ref = shift; - - my $defaults_ref = &queryDefaultXML::ReadDefaultXMLFile( $inputopts_ref, $settings_ref ); - my @keys = keys(%$defaults_ref); - my $csmdata = $$inputopts_ref{'csmdata'}; - my $printing = $$inputopts_ref{'printing'}; - foreach my $var ( @keys ) { - my $value = $$defaults_ref{$var}{'value'}; - my $isafile = $$defaults_ref{$var}{'isfile'}; - # If is a file - if ( $isafile ) { - $value =~ m#$csmdata/(.+?)/([^/]+)$#; - my $dir = $1; - my $file = $2; - - # If file is already in the list then do NOT do anything - if ( defined($list_of_all_files{"$dir/$file"} ) ) { - # Test that this file exists - } elsif ( -f "$value" ) { - print "File $value exists\n" if $printing; - $list_of_all_files{"$dir/$file"} = 1; - } else { - # If doesn't exist add it to the list of files to copy - my $cfile = $$inputopts_ref{'scpfrom'} . "$dir/$file"; - my @dfiles; - if ( defined($$files_ref{$dir}) ) { - my $dir_ref = $$files_ref{$dir}; - @dfiles = @$dir_ref; - my $match = 0; - foreach my $i ( @dfiles ) { - if ( $i eq $cfile ) { $match = 1; } - } - if ( $match == 0 ) { push( @dfiles, $cfile ); } - } else { - @dfiles = ( "$cfile" ); - } - if ( ! defined($$files_ref{$dir}) ) { - print " ADD $cfile to list to copy\n"; - } - $$files_ref{$dir} = \@dfiles; - $list_of_all_files{"$dir/$file"} = 0; - } - } - } - $printTimes++; -} - -#----------------------------------------------------------------------------------------------- - - my %opts = ( - res => undef, - silent => undef, - csmdata => "default", - list => $list, - usrdat => undef, - help => undef, - ); - - my $cmdline = "@ARGV"; - GetOptions( - "d|csmdata=s" => \$opts{'csmdata'}, - "r|res=s" => \$opts{'res'}, - "s|silent" => \$opts{'silent'}, - "u|usrdat=s" => \$opts{'usrdat'}, - "h|elp" => \$opts{'help'}, - ) or usage(); - - # Check for unparsed arguments - if (@ARGV) { - print "ERROR: unrecognized arguments: @ARGV\n"; - usage(); - } - if ( $opts{'help'} ) { - usage(); - } - # Set if should do extra printing or not (if silent mode is not set) - my $printing = 1; - if ( defined($opts{'silent'}) ) { - $printing = 0; - } - # - # Check for required arguments - # - foreach my $req ( "res", "list" ) { - if ( ! defined($opts{$req}) ) { - print "ERROR: $req NOT set and it is a required argument\n"; - usage(); - } - } - my %inputopts; - my @nl_definition_files = ( - "$cfgdir/namelist_files/namelist_definition_ctsm.xml" - ); - $inputopts{'nldef_files'} = \@nl_definition_files; - $inputopts{'empty_cfg_file'} = "config_cache.xml"; - - my $definition = Build::NamelistDefinition->new( $nl_definition_files[0] ); - foreach my $nl_defin_file ( @nl_definition_files ) { - $definition->add( "$nl_defin_file" ); - } - # Resolutions... - my @resolutions; - if ( $opts{'res'} eq "all" ) { - @resolutions = $definition->get_valid_values( "res", 'noquotes'=>1 ); - } else { - @resolutions = split( /,/, $opts{'res'} ); - } - - # Input options - &make_config_cache( "clm5_0", $inputopts{'empty_cfg_file'} ); - push @nl_defaults_files, "$cfgdir/namelist_files/namelist_defaults_ctsm.xml"; - if ( defined($opts{'usrdat'}) ) { - push @nl_defaults_files, "$cfgdir/namelist_files/namelist_defaults_usr_files.xml"; - } - $inputopts{'files'} = \@nl_defaults_files; - $inputopts{'printing'} = $printing; - $inputopts{'ProgName'} = $ProgName; - $inputopts{'cmdline'} = $cmdline; - $inputopts{'cfgdir'} = $cfgdir; - if ( $opts{'csmdata'} eq "default" && $ENV{'CSMDATA'} ne "" ) { - $opts{'csmdata'} = $ENV{'CSMDATA'}; - } - $inputopts{'csmdata'} = $opts{'csmdata'}; - $inputopts{'config'} = "noconfig"; - my %files; - # - # Loop over all resolutions asked for: 1.9x2.5, 10x15, 64x128 etc. - # - foreach my $res ( @resolutions ) { - if ( ! $definition->is_valid_value( "res", "'$res'" ) && $res ne $opts{'usrdat'} ) { - die "ERROR: Input resolution: $res is NOT a valid resolution\n"; - } - $inputopts{'hgrid'} = $res; - print "Resolution = $res\n" if $printing; - my %settings; - if ( $res eq $opts{'usrdat'} ) { - $settings{'clm_usr_name'} = $opts{'usrdat'}; - $settings{'csmdata'} = $opts{'csmdata'}; - $settings{'notest'} = 1; - } - # - # Loop for all possible land masks: USGS, gx1v6, gx3v5 etc. - # - foreach my $mask ( $definition->get_valid_values( "mask", 'noquotes'=>1 ) ) { - print "Mask = $mask \n" if $printing; - $settings{'mask'} = $mask; - # - # Loop over all possible simulation year: 1890, 2000, 2100 etc. - # - $settings{'sim_year_range'} = "constant"; - my @ssp_rcps = $definition->get_valid_values( "ssp_rcp", 'noquotes'=>1 ); - $settings{'ssp_rcp'} = $ssp_rcps[0]; -YEAR: foreach my $sim_year ( $definition->get_valid_values( "sim_year", 'noquotes'=>1 ) ) { - print "sim_year = $sim_year\n" if $printing; - $settings{'sim_year'} = $sim_year; - if ( $sim_year ne 1850 && $sim_year ne 2000 && $sim_year > 1800 ) { next YEAR; } - - my @bgcsettings = $definition->get_valid_values( "bgc_mode", 'noquotes'=>1 ); - print "bgc=@bgcsettings\n" if $printing; - # - # Loop over all possible BGC settings - # - foreach my $bgc ( @bgcsettings ) { - $settings{'bgc'} = $bgc; - my @crop_vals; - if ( $bgc =~ /^cn/ ) { - @crop_vals = ( "on", "off" ); - } else { - @crop_vals = ( "off" ); - } - $settings{'glc_nec'} = 10; - # - # Loop over all possible crop settings - # - foreach my $crop ( @crop_vals ) { - $settings{'crop'} = $crop; - if ( $crop eq "on" ) { - $settings{'maxpft'} = 78; - } else { - $settings{'maxpft'} = 17; - } - $inputopts{'namelist'} = "clm_inparm"; - &GetListofNeededFiles( \%inputopts, \%settings, \%files ); - if ( $printTimes >= 1 ) { - $inputopts{'printing'} = 0; - } - } - } - } - # - # Now do sim-year ranges - # - $settings{'bgc'} = "cn"; - $inputopts{'namelist'} = "clm_inparm"; - foreach my $sim_year_range ( $definition->get_valid_values( "sim_year_range", 'noquotes'=>1 ) ) { - $settings{'sim_year_range'} = $sim_year_range; - if ( $sim_year_range =~ /([0-9]+)-([0-9]+)/ ) { - $settings{'sim_year'} = $1; - } - # - # Loop over all possible ssp_rcp's - # - print "sim_year_range=$sim_year_range ssp_rcp=@ssp_rcps\n" if $printing; - foreach my $ssp_rcp ( @ssp_rcps ) { - $settings{'ssp_rcp'} = $ssp_rcp; - &GetListofNeededFiles( \%inputopts, \%settings, \%files ); - if ( $printTimes >= 1 ) { - $inputopts{'printing'} = 0; - } - } - } - } - } - # - # Loop over directories that need to have files copied into - # - my $hostname; - my $csmdata = $inputopts{'csmdata'}; - open( OUT, ">$list" ) || die "ERROR: trouble opening output file: $list"; - foreach my $dir ( sort(keys(%files)) ) { - if ( $dir eq "." ) { next; } - if ( $dir eq "/" ) { next; } - if ( $dir eq "\n" ) { next; } - if ( $dir eq "" ) { next; } - if ( ! defined($dir) ) { next; } - my $files_ref = $files{$dir}; - my @files = @$files_ref; - foreach my $file ( @files ) { - if ( $file !~ /\n$/ ) { $file = "$file\n"; } - print OUT "file = \$DIN_LOC_ROOT/$file"; - } - } - close( OUT ); - if ( $printing ) { - print "\n\nSuccessful\n\n" - } diff --git a/bld/namelist_files/checkmapfiles.ncl b/bld/namelist_files/checkmapfiles.ncl deleted file mode 100644 index e37100747a..0000000000 --- a/bld/namelist_files/checkmapfiles.ncl +++ /dev/null @@ -1,236 +0,0 @@ -; -; Check that the *_b values are the same between the mapping files -; at the same output resolution. -; -; Erik Kluzek -; Nov/18/2011 -; $Id$ -; $HeadURL; -; - - print( "Check that datm mapping files are consistent" ); - resolutions = (/ "128x256", "64x128", "48x96", "94x192", "0.23x0.31", "0.47x0.63", "0.9x1.25", "1.9x2.5", "2.5x3.33", "4x5", "10x15", "0.125nldas2", "5x5_amazon", "1x1_vancouverCAN", "1x1_mexicocityMEX", "1x1_asphaltjungleNJ", "1x1_brazil", "1x1_urbanc_alpha", "1x1_numaIA", "1x1_smallvilleIA", "ne4np4", "ne16np4", "ne30np4", "ne60np4", "ne120np4", "ne240np4" /); - - space = " "; - badres = 0 - badresolutions = new( (/ 1000 /), string ) - chkres = 0 - chkresolutions = new( (/ 1000 /), string ) - -procedure checkit( desc:string, maxdiff:numeric, res:string, lmask:string, eps:numeric ) -; -; check that difference is within reasonable tolerance... -; -begin - reso = res+"_"+lmask; - if ( maxdiff .gt. eps )then - print( space+space+space+desc+" are off by more than tolerance for "+reso+" resolution" ); - print( space+space+space+"maximum difference = "+maxdiff ); - if ( .not. any(badresolutions .eq. reso ) )then - badresolutions(badres) = reso; - badres = badres + 1 - end if - else - print( space+space+space+"File OK for "+desc+"!" ); - end if - if ( .not. any(chkresolutions .eq. reso ) )then - chkresolutions(chkres) = reso; - chkres = chkres + 1 - end if -end - - -function checkdims( desc:string, dsizefile1 [*]:integer, dsizefile2 [*]:integer, res:string, lmask:string ) -; -; check that dimensions are the same between the file variables -; -begin - reso = res+"_"+lmask; - if ( any( dsizefile1 .ne. dsizefile2) )then - print( space+space+space+desc+" dimensions are different for "+reso+" resolution" ); - print( space+space+space+"dim first file "+dsizefile1 ); - print( space+space+space+"dim second file "+dsizefile2 ); - if ( .not. any(badresolutions .eq. reso ) )then - badresolutions(badres) = reso; - badres = badres + 1 - end if - return( False ); - else - print( space+space+space+"File dims OK for "+desc+"!" ); - return( True ); - end if - if ( .not. any(chkresolutions .eq. reso ) )then - chkresolutions(chkres) = reso; - chkres = chkres + 1 - end if -end - -begin - - csmdata = getenv("CSMDATA"); - clmroot = getenv("CLM_ROOT"); - querynml = "bld/queryDefaultNamelist.pl -silent -justvalue -namelist clmexp"; - if ( .not. ismissing(csmdata) )then - querynml = querynml+" -csmdata "+csmdata; - end if - if ( ismissing(clmroot) )then - querynml = "../../"+querynml; - else - querynml = clmroot+"/components/clm/"+querynml; - end if - - print( "query string="+querynml ) - - - mapgrids = (/"0.5x0.5_nomask", "0.25x0.25_nomask", "0.125x0.125_nomask", "3x3min_nomask", "5x5min_nomask", "10x10min_nomask", "0.9x1.25_nomask", "1km-merge-10min_HYDRO1K-merge-nomask"/); - do i = 0, dimsizes(resolutions)-1 - res = resolutions(i); - print( "Go through maps for Resolution: "+res ); - do j = 0, dimsizes(mapgrids)-1 - grid = str_get_field( mapgrids(j), 1, "_" ); - lmask = str_get_field( mapgrids(j), 2, "_" ); - print( space+"Look for maps from Grid: "+grid+"_"+lmask); - - querynmlres = querynml+" -options frm_lmask="+lmask+",frm_hgrid="+grid+",to_hgrid="+res+",to_lmask=nomask"; - ; - ; Get map filename and open it - ; - mapfile = systemfunc( querynmlres+" -var map" ); - if ( systemfunc("test -f "+mapfile+"; echo $?" ) .ne. 0 )then - delete( mapfile ); - continue; - end if - print( space+"Use mapfile: "+mapfile ); - ncm = addfile( mapfile, "r" ); - - if ( .not. isvar("ncm0") )then - ncm0 = ncm; - else - vars = (/"yc_b", "xc_b", "area_b", "xv_b", "yv_b" /); - k = 0; - if ( checkdims( vars(k), dimsizes(ncm->$vars(k)$), dimsizes(ncm0->$vars(k)$), res, "nomask" ) )then - do k = 0, dimsizes(vars)-1 - maxdiff = max( abs(ncm->$vars(k)$ - ncm0->$vars(k)$) ); - checkit( vars(k), maxdiff, res, "nomask", 1.e-12 ); - delete( maxdiff ); - end do - var = "mask_b" - imaxdiff = max( abs(ncm->$var$ - ncm0->$var$) ); - checkit( var, imaxdiff, res, "nomask", 1.e-12 ); - delete( imaxdiff ); - end if - delete( ncm ); - end if - delete( mapfile ); - - end do - - delete( grid ); - delete( lmask ); - delete( res ); - if ( isvar("ncm0") )then - delete( ncm0 ); - end if - - end do - ; - ; go the other direction now check the _a variables - ; - mksrf_files = (/"mksrf_fvegtyp", "mksrf_fglacier", "mksrf_furbtopo", "mksrf_flai", "mksrf_fsoitex", "mksrf_fsoicol", "mksrf_ffrac", "mksrf_fmax", "mksrf_ftopo", "mksrf_firrig", "mksrf_forganic", "mksrf_flakwat", "mksrf_fwetlnd", "mksrf_furban", "mksrf_fvocef"/) - do i = 0, dimsizes(mapgrids)-1 - grid = str_get_field( mapgrids(i), 1, "_" ); - lmask = str_get_field( mapgrids(i), 2, "_" ); - print( "Grid: "+grid); - print( "Mask: "+lmask); - do j = 0, dimsizes(resolutions)-1 - res = resolutions(j); - print( "res: "+res ); - - querynmlres = querynml+" -options frm_lmask="+lmask+",frm_hgrid="+grid+",to_hgrid="+res+",to_lmask=nomask"; - ; - ; Get map filename and open it - ; - mapfile = systemfunc( querynmlres+" -var map" ); - if ( systemfunc("test -f "+mapfile+"; echo $?" ) .ne. 0 )then - delete( mapfile ); - continue; - end if - print( space+"Use mapfile: "+mapfile ); - ncm = addfile( mapfile, "r" ); - - if ( .not. isvar("ncm0") )then - ncm0 = ncm; - else - vars = (/"yc_a", "xc_a", "area_a", "xv_a", "yv_a" /); - vars2 = (/"LATIXY", "LONGXY", "AREA" /); - k = 0; - if ( checkdims( vars(k), dimsizes(ncm->$vars(k)$), dimsizes(ncm0->$vars(k)$), res, "nomask" ) )then - do k = 0, dimsizes(vars)-1 - maxdiff = max( abs(ncm->$vars(k)$ - ncm0->$vars(k)$) ); - checkit( vars(k), maxdiff, res, "nomask", 1.e-12 ); - delete( maxdiff ); - end do - end if - var = "mask_a" - imaxdiff = max( abs(ncm->$var$ - ncm0->$var$) ); - checkit( var, imaxdiff, res, "nomask", 1.e-12 ); - delete( imaxdiff ); - ; - ; Get mksurfdata input datasets - ; - do k = 0, dimsizes(mksrf_files)-1 - srffile = systemfunc( querynmlres+" -var "+mksrf_files(k) ); - if ( systemfunc("test -f "+srffile+"; echo $?" ) .ne. 0 )then - delete( srffile ); - continue; - end if - print( space+"Use srffile: "+srffile ); - ncs = addfile( srffile, "r" ); - n = 0; - if ( checkdims( vars(n), dimsizes(ncm->$vars(n)$), ndtooned(dimsizes(ncs->$vars2(n)$)), res, "nomask" ) )then - do n = 0, dimsizes(vars2)-1 - maxdiff = max( abs(ncm->$vars(n)$ - ndtooned(ncs->$vars2(n)$)) ); - checkit( vars(n), maxdiff, res, "nomask", 1.e-12 ); - delete( maxdiff ); - end do - var = "mask_a" - var2 = "LANDMASK" - imaxdiff = max( abs(ncm->$var$ - ndtooned(ncs->$var2$)) ); - checkit( var, imaxdiff, res, "nomask", 1.e-12 ); - end if - delete( ncs ); - end do - delete( ncm ); - end if - delete( mapfile ); - - end do - - if ( isvar("vars") )then - delete( vars ) - end if - if ( isvar("vars2") )then - delete( vars2 ) - end if - delete( grid ); - delete( lmask ); - delete( res ); - if ( isvar("ncm0") )then - delete( ncm0 ); - end if - - end do - if ( chkres .gt. 0 )then - print( "resolutions checked = " ); - print( chkresolutions(0:chkres-1) ); - end if - if ( badres .gt. 0 )then - print( "badresolutions = " ); - print( badresolutions(0:badres-1) ); - end if - - print( "===============================" ); - print( "Successfully went through files" ); - -end - diff --git a/bld/namelist_files/createMapEntry.pl b/bld/namelist_files/createMapEntry.pl deleted file mode 100755 index f9009ba86f..0000000000 --- a/bld/namelist_files/createMapEntry.pl +++ /dev/null @@ -1,73 +0,0 @@ -#!/usr/bin/env perl -# -# July 18 2012 Muszala -# -# createMapEntry.pl - A simple script to dump a list of mappings for a specified resolution to then -# cut and paste into namelist_defaults_ctsm.xml. A better way is to write the output of this script -# to a file and then directly insert that file into namelist_defaults_ctsm.xml (using :r foo in vim for -# example). -# -# Example usage:>> ./createMapEntry.pl 1x1_brazil -# will create XML entries for maps in ../lnd/clm2/mappingdata/maps/1x1_brazil such as: -# -# lnd/clm2/mappingdata/maps/1x1_brazil/map_0.5x0.5_AVHRR_to_1x1_brazil_nomask_aave_da_c120717.nc -# -use Cwd; -use strict; -use English; -use IO::File; -use Getopt::Long; - - my $date = scalar localtime() ; - my $scriptName; - ($scriptName = $0) =~ s!(.*)/!!; # get name of script - my $cwd = getcwd(); - my $CSMDATA = "/glade/campaign/cesm/cesmdata/cseg/inputdata"; - - if ($#ARGV != 0 ) { - usage(); - exit; - } - my $grid=$ARGV[0]; - - sub usage { - die < - is the resolution to use to dump text to paste into namelist_defaults_ctsm.xml -EOF - } - - #~# set up directory paths - my $pathStub="lnd/clm2/mappingdata/maps"; - my $partialPath="$pathStub/$grid"; - my $fullPath = "$CSMDATA/$partialPath"; - - #~# open and read directory - opendir DIR, $fullPath or die "Cannot read dir! $fullPath"; - my @list = readdir DIR; - - #~# print a unique start string in the XML comments - print "\n"; - print "\n \n\n"; - - foreach my $foo ( @list ) { - next if ($foo =~ m/^\./); #~# skip anything in the directory with a leading or stand alone 'dot' - $foo =~ s/$grid/RES/; # Replace grid trying to match with RES (so underscores in the grid name don't mess up the matching) - my @tokens = split(/_/, $foo); #~# split foo name by the underscore - #~# write out lines for namelist_defaults_ctsm.xml nomask" files - my $from_mask = $tokens[2]; - if ( $from_mask =~ /nomask/ ) { - if ( $tokens[5] eq "nomask" && $tokens[4] eq "RES" ) { - print "$partialPath/$foo\n"; - } - } - } - - #~# print a unique end string in the XML comments - print "\n \n"; - closedir(DIR); - exit 0; diff --git a/bld/namelist_files/createMkSrfEntry.py b/bld/namelist_files/createMkSrfEntry.py deleted file mode 100755 index 3f12df1509..0000000000 --- a/bld/namelist_files/createMkSrfEntry.py +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/env python3 - -import os, sys - -class mksrfDataEntry_prog: - - # Class data - year_start = 850 - year_end = 1849 - ssp_rcp = "hist" - subdir = "pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012" - cdate = 171012 - desc = "histclm50_LUH2" - - def parse_cmdline_args( self ): - "Parse the command line arguments for create data entry list" - from optparse import OptionParser, OptionGroup - - parser = OptionParser( usage="%prog [options]" ) - options = OptionGroup( parser, "Options" ) - options.add_option( "-s", "--year_start", dest="year_start", default=self.year_start, \ - help="Start year" ) - options.add_option( "-f", "--year_end", dest="year_end", default=self.year_end, \ - help="End year" ) - options.add_option( "-d", "--subdir", dest="subdir", default=self.subdir, \ - help="Subdirectory" ) - options.add_option( "--cdate", dest="cdate", default=self.cdate, \ - help="Creation date" ) - options.add_option( "--desc", dest="desc", default=self.desc, \ - help="Description string" ) - parser.add_option_group(options) - (options, args) = parser.parse_args() - if len(args) != 0: - parser.error("incorrect number of arguments") - - self.year_start = options.year_start - self.year_end = options.year_end - self.subdir = options.subdir - self.cdate = options.cdate - self.desc = options.desc - - def printentry( self, year ): - "Print a single entry" - print( 'lnd/clm2/rawdata/%s/mksrf_landuse_%s_%s.c%s.nc' % (self.subdir, self.desc, year, self.cdate) ) - print( '\n' ) - -entry = mksrfDataEntry_prog() -entry.parse_cmdline_args() - -for year in range(entry.year_start, entry.year_end+1): - entry.printentry( year ) - - - - diff --git a/bld/namelist_files/namelist_defaults_ctsm.xml b/bld/namelist_files/namelist_defaults_ctsm.xml index a01839836d..ecced7a6e2 100644 --- a/bld/namelist_files/namelist_defaults_ctsm.xml +++ b/bld/namelist_files/namelist_defaults_ctsm.xml @@ -38,25 +38,20 @@ attributes from the config_cache.xml file (with keys converted to upper-case). clm4_5_CRUv7 clm5_0_cam6.0 clm5_1_GSWP3v1 +clm6_0_GSWP3v1 - -clm2 -clm2 -clm2 + +clm2 off -2 -2 -1 -2 -2 -2 -2 +2 +1 +2 1 -0 +0 .true. @@ -83,31 +78,25 @@ attributes from the config_cache.xml file (with keys converted to upper-case). -8760 20 - -.false. -.false. -.false. + +.false. -.true. -.true. +.true. .false. -2 -2 +2 1 0 -.true. -.true. +.true. .false. -Medlyn2011 -Medlyn2011 -Ball-Berry1987 +Medlyn2011 +Ball-Berry1987 lnd/clm2/isotopes/atm_delta_C13_CMIP6_1850-2015_yearly_v2.0_c190528.nc @@ -127,14 +116,9 @@ attributes from the config_cache.xml file (with keys converted to upper-case). lnd/clm2/isotopes/atm_delta_C14_CMIP6_SSP5B_3x1_global_1850-2100_yearly_c181209.nc -.true. -.false. -.true. -.false. -.false. - .false. - +.true. +.false. .false. @@ -149,76 +133,62 @@ attributes from the config_cache.xml file (with keys converted to upper-case). ALL -0.50,0.30 -0.50,0.30 +0.50,0.30 0.60,0.40 -ON_WASTEHEAT -ON_WASTEHEAT +ON_WASTEHEAT ON -1 -1 +1 0 -FAST -FAST +FAST NONE .false. +.false. .true. -.false. -.false. 4SL_2m -20SL_8.5m -20SL_8.5m +20SL_8.5m 10SL_3.5m -.false. -.false. -.true. -.false. -.false. -.true. +.false. +.false. +.true. .false. -1 -1 +1 0 -1 -1 -1 + +1 -1 -1 +1 0 -1.d-2 -0.001d00 -1.d-2 -0.001d00 -1.d-2 +0.001d00 +1.d-2 1.d-2 2.0d00 2.0d00 0.5d00 -0.5d00 -2.0d00 +0.5d00 +2.0d00 +0.5d00 +2.0d00 -.true. -.true. +.true. .false. .true. @@ -233,28 +203,24 @@ attributes from the config_cache.xml file (with keys converted to upper-case). 0. 2. - -0. -2. - --2. -0. - --2. -0. +-2. +0. + +0. +2. +.true. .false. -.true. -.true. -li2021gswpfrc +li2021gswpfrc li2016crufrc li2014qianfrc @@ -283,6 +249,22 @@ attributes from the config_cache.xml file (with keys converted to upper-case). >20.0d00 20.0d00 +20.0d00 +20.0d00 +20.0d00 +20.0d00 +20.0d00 +20.0d00 +20.0d00 +20.0d00 80.0d00 0.85d00 0.98d00 @@ -298,6 +280,22 @@ attributes from the config_cache.xml file (with keys converted to upper-case). >0.008d00 0.008d00 +0.008d00 +0.008d00 +0.008d00 +0.008d00 +0.008d00 +0.008d00 +0.008d00 +0.008d00 0.17d-3 1.6d-4 0.33d00 @@ -322,39 +320,32 @@ attributes from the config_cache.xml file (with keys converted to upper-case). 0.28d00 -.false. -.false. +.false. .true. -.true. -.false. -.false. +.true. +.false. +.false. +.false. 40 3 -.true. -1.0 -0.05 - -.true. -1.0 -0.05 - +.true. +1.0 +0.05 .false. 0.25 1.0 +1 0 -1 -1 +1 1 -1 -1 4 2 @@ -375,14 +366,11 @@ attributes from the config_cache.xml file (with keys converted to upper-case). 14400 -3400. 0.6 -1.0 -1.0 +1.0 0.5 0.1 - -.false. -.false. + .false. .false. @@ -393,19 +381,15 @@ attributes from the config_cache.xml file (with keys converted to upper-case). .true. -12 -5 -12 -5 -5 +12 +5 +5 -10000.0 -5000.0 -10000.0 -5000.0 -1000.0 +10000.0 +5000.0 +1000.0 0.010d00 0.015d00 @@ -414,30 +398,24 @@ attributes from the config_cache.xml file (with keys converted to upper-case). 0.02d00 0.05d00 -2000. -2000. +2000. 1.e30 -10.0d00 -10.0d00 +10.0d00 10.0 -.true. -.true. +.true. .false. -'Vionnet2012' -'Vionnet2012' +'Vionnet2012' 'Anderson1976' -'Slater2017' -'Slater2017' +'Slater2017' 'TruncatedAnderson1976' +175.d00 100.d00 -175.d00 -175.d00 0.08d00 @@ -486,14 +464,14 @@ attributes from the config_cache.xml file (with keys converted to upper-case). simplicity, we tie the defaults for both of these options to the overall CLM phys version, rather than having some intermediate option that controls the defaults for both h2osno_max and glc_snow_persistence_max_days. --> -0 -0 +0 7300 +lnd/clm2/paramdata/ctsm60_params.c240208.nc lnd/clm2/paramdata/ctsm51_params.c240208.nc lnd/clm2/paramdata/clm50_params.c240208.nc lnd/clm2/paramdata/clm45_params.c240208.nc @@ -510,6 +488,7 @@ attributes from the config_cache.xml file (with keys converted to upper-case). ZengWang2007 Meier2022 +Meier2022 .true. .false. @@ -517,19 +496,14 @@ attributes from the config_cache.xml file (with keys converted to upper-case). -.true. -.false. -.true. -.false. -.false. +.false. +.true. +.false. -.true. -.false. -.true. -.false. -.false. -.false. +.true. +.false. +.false. .true. @@ -548,84 +522,73 @@ attributes from the config_cache.xml file (with keys converted to upper-case). .true. .false. -.false. -.true. -.true. -.true. +.false. +.true. -0.17 -0.17 + +0.17 unset .false. +.true. .false. -.true. -.true. -0.d+0 +0.d+0 0.5d00 +0.5d00 +varytropicsbylat +12.0d00 +0.4d00 constant -varytropicsbylat -12.0d00 -0.4d00 -varytropicsbylat -12.0d00 -0.4d00 - -3.d00 -3.d00 + +3.d00 1.d00 -.true. -DependsOnLat -.false. -Constant -.false. -.true. +Constant +DependsOnLat +DependsOnLat + +.false. +.true. +.true. + +.false. +.true. +.true. .false. -.true. -.true. .true. -.false. -.false. -.false. -.false. -.false. -.false. +.false. -.false. -.false. -.true. -.false. -.true. - -1.d-9 -1.d-9 +.false. +.true. +.false. + +1.d-9 1.d-8 --6.d+1 --6.d+0 --6.d+1 --6.d+0 + +-6.d+1 -6.d+2 + +-6.d+0 -6.d+1 .false. -.false. .false. +.false. .false. Darcy LayerSum @@ -635,8 +598,8 @@ attributes from the config_cache.xml file (with keys converted to upper-case). .false. -.true. -.true. +.true. +.false. @@ -665,8 +628,13 @@ attributes from the config_cache.xml file (with keys converted to upper-case). -.true. - +.true. + + .true. @@ -683,9 +651,51 @@ attributes from the config_cache.xml file (with keys converted to upper-case). .true. + + +.true. +.true. +.true. +.true. + +.true. + + +.true. + + + +.true. +.true. +.true. +.true. + +.true. + + +.true. + + -.true. -.true. +.true. +.true. +.true. .true. .true. @@ -698,8 +708,10 @@ attributes from the config_cache.xml file (with keys converted to upper-case). .false. .false. .false. +.false. +.false. -.false. +.false. + +hgrid=0.9x1.25 maxpft=17 mask=gx1v7 use_cn=.false. use_crop=.false. irrigate=.true. glc_nec=10 do_transient_pfts=.false. + + +hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.false. glc_nec=10 do_transient_pfts=.false. + + + +hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.false. glc_nec=10 do_transient_pfts=.false. + + hgrid=1.9x2.5 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. @@ -776,8 +803,7 @@ attributes from the config_cache.xml file (with keys converted to upper-case). hgrid=1.9x2.5 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. - -hgrid=1.9x2.5 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. @@ -788,7 +814,12 @@ attributes from the config_cache.xml file (with keys converted to upper-case). hgrid=1.9x2.5 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. - + +hgrid=1.9x2.5 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. + + + hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. @@ -834,16 +865,6 @@ attributes from the config_cache.xml file (with keys converted to upper-case). >hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. -hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. - - -hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. - - hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. @@ -861,7 +882,11 @@ attributes from the config_cache.xml file (with keys converted to upper-case). hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. + + + +hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. @@ -903,7 +928,7 @@ attributes from the config_cache.xml file (with keys converted to upper-case). - + hgrid=0.9x1.25 maxpft=17 mask=gx1v7 use_cn=.false. use_crop=.false. irrigate=.true. glc_nec=10 do_transient_pfts=.false. @@ -975,7 +1000,7 @@ attributes from the config_cache.xml file (with keys converted to upper-case). ic_ymd="18500101" sim_year="1850" do_transient_pfts=".false." ic_tod="0" glc_nec="10" use_crop=".true." irrigate=".false." lnd_tuning_mode="clm5_0_GSWP3v1" ->lnd/clm2/initdata_map/clmi.I1850Clm50BgcCrop-ciso.1366-01-01.0.9x1.25_gx1v7_simyr1850_c200428.nc +>lnd/clm2/initdata_esmf/ctsm5.2/clmi.I1850Clm50BgcCrop-ciso.1366-01-01.0.9x1.25_gx1v7_simyr1850_c240223.nc @@ -983,7 +1008,7 @@ attributes from the config_cache.xml file (with keys converted to upper-case). ic_ymd="18500101" sim_year="1850" do_transient_pfts=".false." ic_tod="0" glc_nec="10" use_crop=".true." irrigate=".false." lnd_tuning_mode="clm5_0_CRUv7" ->lnd/clm2/initdata_map/clmi.I1850Clm50BgcCropCru-ciso.1526-01-01.0.9x1.25_gx1v7_simyr1850_c200728.nc +>lnd/clm2/initdata_esmf/ctsm5.2/clmi.I1850Clm50BgcCropCru-ciso.1526-01-01.0.9x1.25_gx1v7_simyr1850_c240223.nc @@ -1012,9 +1037,9 @@ attributes from the config_cache.xml file (with keys converted to upper-case). ic_ymd="18500101" sim_year="1850" do_transient_pfts=".false." ic_tod="0" glc_nec="10" use_crop=".true." irrigate=".false." lnd_tuning_mode="clm5_1_GSWP3v1" ->lnd/clm2/initdata_map/clmi.I1850Clm50BgcCrop-ciso.1366-01-01.0.9x1.25_gx1v7_simyr1850_c200428.nc +>lnd/clm2/initdata_esmf/ctsm5.2/clmi.I1850Clm50BgcCrop-ciso.1366-01-01.0.9x1.25_gx1v7_simyr1850_c240223.nc - + lnd/clm2/initdata_map/clmi.B1850Clm50BgcCrop.0161-01-01.0.9x1.25_gx1v7_simyr1850_c200729.nc + +lnd/clm2/initdata_map/clmi.I1850Clm50Sp.0181-01-01.0.9x1.25_gx1v7_simyr1850_c200806.nc + +lnd/clm2/initdata_esmf/ctsm5.2/clmi.I1850Clm50BgcCrop-ciso.1366-01-01.0.9x1.25_gx1v7_simyr1850_c240223.nc + + + +lnd/clm2/initdata_map/clmi.B1850Clm50BgcCrop.0161-01-01.0.9x1.25_gx1v7_simyr1850_c200729.nc + + @@ -1041,7 +1088,7 @@ attributes from the config_cache.xml file (with keys converted to upper-case). ic_ymd="20110101" sim_year="2000" do_transient_pfts=".false." ic_tod="0" glc_nec="10" use_crop=".true." irrigate=".true." lnd_tuning_mode="clm4_5_CRUv7" ->lnd/clm2/initdata_map/clmi.I2000Clm50BgcCrop.2011-01-01.1.9x2.5_gx1v7_gl4_simyr2000_c190312.nc +>lnd/clm2/initdata_esmf/ctsm5.2/clmi.I2000Clm50BgcCrop.2011-01-01.1.9x2.5_gx1v7_gl4_simyr2000_c240223.nc @@ -1049,13 +1096,19 @@ attributes from the config_cache.xml file (with keys converted to upper-case). ic_ymd="20110101" sim_year="2000" do_transient_pfts=".false." ic_tod="0" glc_nec="10" use_crop=".true." irrigate=".true." lnd_tuning_mode="clm5_0_GSWP3v1" ->lnd/clm2/initdata_map/clmi.I2000Clm50BgcCrop.2011-01-01.1.9x2.5_gx1v7_gl4_simyr2000_c190312.nc +>lnd/clm2/initdata_esmf/ctsm5.2/clmi.I2000Clm50BgcCrop.2011-01-01.1.9x2.5_gx1v7_gl4_simyr2000_c240223.nc lnd/clm2/initdata_map/clmi.I2000Clm50BgcCrop.2011-01-01.1.9x2.5_gx1v7_gl4_simyr2000_c190312.nc +>lnd/clm2/initdata_esmf/ctsm5.2/clmi.I2000Clm50BgcCrop.2011-01-01.1.9x2.5_gx1v7_gl4_simyr2000_c240223.nc + +lnd/clm2/initdata_esmf/ctsm5.2/clmi.I2000Clm50BgcCrop.2011-01-01.1.9x2.5_gx1v7_gl4_simyr2000_c240223.nc @@ -1064,7 +1117,7 @@ attributes from the config_cache.xml file (with keys converted to upper-case). ic_ymd="20110101" sim_year="2000" do_transient_pfts=".false." ic_tod="0" glc_nec="10" use_crop=".true." irrigate=".true." lnd_tuning_mode="clm5_0_CRUv7" ->lnd/clm2/initdata_map/clmi.I2000Clm50BgcCrop.2011-01-01.1.9x2.5_gx1v7_gl4_simyr2000_c190312.nc +>lnd/clm2/initdata_esmf/ctsm5.2/clmi.I2000Clm50BgcCrop.2011-01-01.1.9x2.5_gx1v7_gl4_simyr2000_c240223.nc @@ -1075,6 +1128,10 @@ attributes from the config_cache.xml file (with keys converted to upper-case). >lnd/clm2/initdata_map/clmi.BHIST.2000-01-01.0.9x1.25_gx1v7_simyr1979_c200806.nc + + lnd/clm2/initdata_map/clmi.BHIST.2000-01-01.0.9x1.25_gx1v7_simyr2000_c200728.nc +lnd/clm2/initdata_map/clmi.BHIST.2000-01-01.0.9x1.25_gx1v7_simyr2000_c200728.nc + + lnd/clm2/initdata_map/clmi.FHISTSp.2013-01-01.ne0CONUSne30x8_mt12_simyr2013_c200806.nc + +lnd/clm2/initdata_map/clmi.BHIST.2000-01-01.0.9x1.25_gx1v7_simyr1979_c200806.nc + + +lnd/clm2/initdata_map/clmi.BHIST.2000-01-01.1.9x2.5_gx1v7_simyr1979_c200806.nc + + + +lnd/clm2/initdata_map/clmi.FHISTSp.1979-01-01.ARCTIC_ne30x4_mt12_simyr1979_c200806.nc + + + +lnd/clm2/initdata_map/clmi.FHISTSp.1979-01-01.ARCTICGRIS_ne30x8_mt12_simyr1979_c200806.nc + + + +lnd/clm2/initdata_map/clmi.F2000.2000-01-01.ne120pg3_mt13_simyr2000_c200728.nc + + + +lnd/clm2/initdata_map/clmi.BHIST.2000-01-01.0.9x1.25_gx1v7_simyr2000_c200728.nc + + + +lnd/clm2/initdata_map/clmi.BHISTSp.2000-01-01.1.9x2.5_gx1v7_simyr2003_c200807.nc + + + + +lnd/clm2/initdata_map/clmi.FHISTSp.2013-01-01.ne0CONUSne30x8_mt12_simyr2013_c200806.nc + + +lnd/clm2/initdata_map/clmi.BHIST.2000-01-01.0.9x1.25_gx1v7_simyr1979_c200806.nc + + +lnd/clm2/initdata_map/clmi.BHIST.2000-01-01.1.9x2.5_gx1v7_simyr1979_c200806.nc + + + +lnd/clm2/initdata_map/clmi.FHISTSp.1979-01-01.ARCTIC_ne30x4_mt12_simyr1979_c200806.nc + + + +lnd/clm2/initdata_map/clmi.FHISTSp.1979-01-01.ARCTICGRIS_ne30x8_mt12_simyr1979_c200806.nc + + + +lnd/clm2/initdata_map/clmi.F2000.2000-01-01.ne120pg3_mt13_simyr2000_c200728.nc + + + +lnd/clm2/initdata_map/clmi.BHIST.2000-01-01.0.9x1.25_gx1v7_simyr2000_c200728.nc + + + +lnd/clm2/initdata_map/clmi.BHISTSp.2000-01-01.1.9x2.5_gx1v7_simyr2003_c200807.nc + + + + +lnd/clm2/initdata_map/clmi.FHISTSp.2013-01-01.ne0CONUSne30x8_mt12_simyr2013_c200806.nc + + - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_48x96_hist_16pfts_Irrig_CMIP6_simyr2000_c190214.nc - - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_0.9x1.25_hist_16pfts_Irrig_CMIP6_simyr2000_c190214.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_0.9x1.25_hist_16pfts_Irrig_CMIP6_simyr2000_c190214.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_1.9x2.5_hist_16pfts_Irrig_CMIP6_simyr2000_c190304.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_1.9x2.5_hist_16pfts_Irrig_CMIP6_simyr2000_c190304.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_4x5_hist_16pfts_Irrig_CMIP6_simyr2000_c190214.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_10x15_hist_16pfts_Irrig_CMIP6_simyr2000_c190214.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_10x15_hist_16pfts_Irrig_CMIP6_simyr2000_c190214.nc - - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_ne30np4_hist_16pfts_Irrig_CMIP6_simyr2000_c190303.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_ne16np4_hist_16pfts_Irrig_CMIP6_simyr2000_c190214.nc - - -lnd/clm2/surfdata_map/surfdata_0.125nldas2_hist_16pfts_Irrig_CMIP6_simyr2005_c190412.nc + + + +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_0.9x1.25_hist_2000_16pfts_c240216.nc + +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_1.9x2.5_hist_2000_16pfts_c240216.nc + +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_10x15_hist_2000_16pfts_c240216.nc + +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_4x5_hist_2000_16pfts_c240216.nc + +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_mpasa60_hist_2000_16pfts_c240216.nc + +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_mpasa15_hist_2000_16pfts_c240216.nc + + +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_mpasa3p75_hist_2000_16pfts_c240216.nc + + + + +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_0.9x1.25_hist_2000_78pfts_c240216.nc + +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_0.9x1.25_hist_2000_78pfts_c240216.nc + +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_1.9x2.5_hist_2000_78pfts_c240216.nc + +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_1.9x2.5_hist_2000_78pfts_c240216.nc + +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_10x15_hist_2000_78pfts_c240216.nc + +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_10x15_hist_2000_78pfts_c240216.nc + +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_4x5_hist_2000_78pfts_c240216.nc + +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_4x5_hist_2000_78pfts_c240216.nc -lnd/clm2/surfdata_map/ctsm5.1.dev116/surfdata_1x1_brazil_hist_78pfts_CMIP6_simyr2000_c230123.nc - - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_5x5_amazon_hist_16pfts_Irrig_CMIP6_simyr2000_c190214.nc - - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_64x128_hist_16pfts_Irrig_CMIP6_simyr2000_c190214.nc - - - -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_C384_hist_78pfts_CMIP6_simyr2000_c200317.nc - -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_C192_hist_78pfts_CMIP6_simyr2000_c200317.nc - -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_C96_hist_78pfts_CMIP6_simyr2000_c200317.nc - -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_C48_hist_78pfts_CMIP6_simyr2000_c200317.nc - -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_C24_hist_78pfts_CMIP6_simyr2000_c200317.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_0.9x1.25_hist_78pfts_CMIP6_simyr2000_c190214.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_1.9x2.5_hist_78pfts_CMIP6_simyr2000_c190304.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_360x720cru_78pfts_CMIP6_simyr2000_c170824.nc - -lnd/clm2/surfdata_map/release-clm5.0.24/surfdata_0.125x0.125_hist_78pfts_CMIP6_simyr2005_c190624.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_10x15_hist_78pfts_CMIP6_simyr2000_c190214.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_4x5_hist_78pfts_CMIP6_simyr2000_c190214.nc - -lnd/clm2/surfdata_map/ctsm5.1.dev116/surfdata_1x1_numaIA_hist_78pfts_CMIP6_simyr2000_c230123.nc - -lnd/clm2/surfdata_map/ctsm5.1.dev116/surfdata_1x1_smallvilleIA_hist_78pfts_CMIP6_simyr2000_c230123.nc +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_1x1_brazil_hist_2000_78pfts_c240221.nc + +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_5x5_amazon_hist_2000_78pfts_c240216.nc + + + +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_ne30np4_hist_2000_78pfts_c240216.nc + +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_ne30np4.pg2_hist_2000_78pfts_c240216.nc + +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_ne30np4.pg3_hist_2000_78pfts_c240216.nc + +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_ne16np4.pg3_hist_2000_78pfts_c240216.nc + + +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_0.125nldas2_hist_2000_78pfts_c240216.nc + + +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_360x720cru_hist_2000_78pfts_c240216.nc + +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_C96_hist_2000_78pfts_c240216.nc + + +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_1x1_numaIA_hist_2000_78pfts_c240221.nc + -lnd/clm2/surfdata_map/ctsm5.1.dev052/surfdata_mpasa480_hist_78pfts_CMIP6_simyr2000_c211110.nc - -lnd/clm2/surfdata_map/ctsm5.1.dev052/surfdata_mpasa240_hist_78pfts_CMIP6_simyr2000_c211115.nc +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_mpasa480_hist_2000_78pfts_c240216.nc -lnd/clm2/surfdata_map/ctsm5.1.dev052/surfdata_mpasa120_hist_78pfts_CMIP6_simyr2000_c211108.nc - -lnd/clm2/surfdata_map/ctsm5.1.dev052/surfdata_mpasa60_hist_78pfts_CMIP6_simyr2000_c211110.nc - -lnd/clm2/surfdata_map/ctsm5.1.dev052/surfdata_mpasa30_hist_78pfts_CMIP6_simyr2000_c211111.nc - -lnd/clm2/surfdata_map/ctsm5.1.dev052/surfdata_mpasa15_hist_78pfts_CMIP6_simyr2000_c211111.nc +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_mpasa120_hist_2000_78pfts_c240216.nc -lnd/clm2/surfdata_map/ctsm5.1.dev120//surfdata_ne3np4.pg3_hist_78pfts_CMIP6_simyr2000_c230405.nc - -lnd/clm2/surfdata_map/ctsm5.1.dev120/surfdata_ne5np4.pg3_hist_78pfts_CMIP6_simyr2000_c230405.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_ne16np4_hist_78pfts_CMIP6_simyr2000_c190214.nc - -lnd/clm2/surfdata_map/ctsm5.1.dev120/surfdata_ne16np4.pg3_hist_78pfts_CMIP6_simyr2000_c230405.nc - -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_ne30np4_hist_78pfts_CMIP6_simyr2000_c200426.nc - -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_ne30np4.pg2_hist_78pfts_CMIP6_simyr2000_c200426.nc - -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_ne30np4.pg3_hist_78pfts_CMIP6_simyr2000_c200426.nc - -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_ne120np4_hist_78pfts_CMIP6_simyr2000_c200427.nc - -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_ne120np4.pg2_hist_78pfts_CMIP6_simyr2000_c200426.nc +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_ne3np4.pg3_hist_2000_78pfts_c240216.nc -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_ne120np4.pg3_hist_78pfts_CMIP6_simyr2000_c200427.nc +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_ne120np4.pg3_hist_2000_78pfts_c240216.nc -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_ne0np4.ARCTICGRIS.ne30x8_hist_78pfts_CMIP6_simyr2000_c200426.nc +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_ne0np4.ARCTICGRIS.ne30x8_hist_2000_78pfts_c240216.nc -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_ne0np4.ARCTIC.ne30x4_hist_78pfts_CMIP6_simyr2000_c200426.nc +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_ne0np4.ARCTIC.ne30x4_hist_2000_78pfts_c240216.nc -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_ne0np4.CONUS.ne30x8_hist_78pfts_CMIP6_simyr2000_c200426.nc +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_ne0np4CONUS.ne30x8_hist_2000_78pfts_c240216.nc -lnd/clm2/surfdata_map/ctsm5.1.dev116/surfdata_1x1_vancouverCAN_hist_78pfts_CMIP6_simyr2000_c230123.nc +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_1x1_vancouverCAN_hist_2000_78pfts_c240221.nc -lnd/clm2/surfdata_map/ctsm5.1.dev116/surfdata_1x1_mexicocityMEX_hist_78pfts_CMIP6_simyr2000_c230123.nc +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_1x1_mexicocityMEX_hist_2000_78pfts_c240221.nc -lnd/clm2/surfdata_map/ctsm5.1.dev116/surfdata_1x1_urbanc_alpha_hist_78pfts_CMIP6_simyr2000_c230123.nc - - - - lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_48x96_hist_16pfts_Irrig_CMIP6_simyr1850_c190214.nc - - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_0.9x1.25_hist_16pfts_Irrig_CMIP6_simyr1850_c190214.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_1.9x2.5_hist_16pfts_Irrig_CMIP6_simyr1850_c190304.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_10x15_hist_16pfts_Irrig_CMIP6_simyr1850_c190214.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_4x5_hist_16pfts_Irrig_CMIP6_simyr1850_c190214.nc - - -lnd/clm2/surfdata_map/ctsm5.1.dev052/surfdata_mpasa480_hist_78pfts_CMIP6_simyr1850_c211110.nc - -lnd/clm2/surfdata_map/ctsm5.1.dev052/surfdata_mpasa240_hist_78pfts_CMIP6_simyr1850_c211115.nc - -lnd/clm2/surfdata_map/ctsm5.1.dev052/surfdata_mpasa120_hist_78pfts_CMIP6_simyr1850_c211108.nc - -lnd/clm2/surfdata_map/ctsm5.1.dev052/surfdata_mpasa60_hist_78pfts_CMIP6_simyr1850_c211110.nc - -lnd/clm2/surfdata_map/ctsm5.1.dev052/surfdata_mpasa30_hist_78pfts_CMIP6_simyr1850_c211111.nc - -lnd/clm2/surfdata_map/ctsm5.1.dev052/surfdata_mpasa15_hist_78pfts_CMIP6_simyr1850_c211111.nc - - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_ne30np4_hist_16pfts_Irrig_CMIP6_simyr1850_c190303.nc - - - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_48x96_hist_78pfts_CMIP6_simyr1850_c190214.nc - - -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_C384_hist_78pfts_CMIP6_simyr1850_c200317.nc - -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_C192_hist_78pfts_CMIP6_simyr1850_c200317.nc +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_1x1_urbanc_alpha_hist_2000_78pfts_c240221.nc + + + + +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_360x720cru_hist_1850_78pfts_c240216.nc + +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_0.9x1.25_hist_1850_78pfts_c240216.nc + +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_1.9x2.5_hist_1850_78pfts_c240216.nc + +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_10x15_hist_1850_78pfts_c240216.nc + +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_4x5_hist_1850_78pfts_c240216.nc + + +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_mpasa480_hist_1850_78pfts_c240216.nc + +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_mpasa120_hist_1850_78pfts_c240216.nc + + +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_ne30np4_hist_1850_78pfts_c240216.nc + +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_ne30np4.pg2_hist_1850_78pfts_c240216.nc + +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_ne30np4.pg3_hist_1850_78pfts_c240216.nc + +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_ne3np4.pg3_hist_1850_78pfts_c240216.nc + -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_C96_hist_78pfts_CMIP6_simyr1850_c200317.nc - -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_C48_hist_78pfts_CMIP6_simyr1850_c200317.nc - -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_C24_hist_78pfts_CMIP6_simyr1850_c200317.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_0.9x1.25_hist_78pfts_CMIP6_simyr1850_c190214.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_1.9x2.5_hist_78pfts_CMIP6_simyr1850_c190304.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_10x15_hist_78pfts_CMIP6_simyr1850_c190214.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_4x5_hist_78pfts_CMIP6_simyr1850_c190214.nc +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_C96_hist_1850_78pfts_c240216.nc -lnd/clm2/surfdata_map/ctsm5.1.dev116/surfdata_1x1_smallvilleIA_hist_78pfts_CMIP6_simyr1850_c230123.nc - -lnd/clm2/surfdata_map/ctsm5.1.dev116/surfdata_1x1_numaIA_hist_78pfts_CMIP6_simyr1850_c230123.nc - - -lnd/clm2/surfdata_map/ctsm5.1.dev116/surfdata_1x1_brazil_hist_78pfts_CMIP6_simyr1850_c230123.nc +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_1x1_smallvilleIA_hist_1850_78pfts_c240221.nc + +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_1x1_brazil_hist_1850_78pfts_c240221.nc -lnd/clm2/surfdata_map/ctsm5.1.dev120/surfdata_ne3np4.pg3_hist_78pfts_CMIP6_simyr1850_c230405.nc - -lnd/clm2/surfdata_map/ctsm5.1.dev120/surfdata_ne5np4.pg3_hist_78pfts_CMIP6_simyr1850_c230405.nc +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_ne3np4.pg3_hist_1850_78pfts_c240216.nc -lnd/clm2/surfdata_map/ctsm5.1.dev120/surfdata_ne16np4.pg3_hist_78pfts_CMIP6_simyr1850_c230405.nc - -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_ne30np4_hist_78pfts_CMIP6_simyr1850_c200426.nc - -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_ne30np4.pg2_hist_78pfts_CMIP6_simyr1850_c200426.nc - -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_ne30np4.pg3_hist_78pfts_CMIP6_simyr1850_c200426.nc - -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_ne120np4_hist_78pfts_CMIP6_simyr1850_c200427.nc - -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_ne120np4.pg2_hist_78pfts_CMIP6_simyr1850_c200426.nc +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_ne16np4.pg3_hist_1850_78pfts_c240216.nc -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_ne120np4.pg3_hist_78pfts_CMIP6_simyr1850_c200427.nc +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_ne120np4.pg3_hist_1850_78pfts_c240216.nc -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_ne0np4.ARCTICGRIS.ne30x8_hist_78pfts_CMIP6_simyr1850_c200426.nc +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_ne0np4.ARCTICGRIS.ne30x8_hist_1850_78pfts_c240216.nc -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_ne0np4.ARCTIC.ne30x4_hist_78pfts_CMIP6_simyr1850_c200426.nc +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_ne0np4.ARCTIC.ne30x4_hist_1850_78pfts_c240216.nc -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_ne0np4.CONUS.ne30x8_hist_78pfts_CMIP6_simyr1850_c200426.nc +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_ne0np4CONUS.ne30x8_hist_1850_78pfts_c240216.nc -lnd/clm2/surfdata_map/surfdata_0.9x1.25_hist_16pfts_nourb_CMIP6_simyrPtVg_c181114.nc +lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_0.9x1.25_PtVeg_nourb_1850_16pfts_c240216.nc -lnd/clm2/surfdata_map/NEON/16PFT_mixed/surfdata_1x1_NEON_${NEONSITE}_hist_16pfts_Irrig_CMIP6_simyr2000_c230120.nc +lnd/clm2/surfdata_esmf/NEON/16PFT_mixed/surfdata_1x1_NEON_${NEONSITE}_hist_2000_16pfts_c240206.nc -lnd/clm2/surfdata_map/NEON/surfdata_1x1_NEON_${NEONSITE}_hist_78pfts_CMIP6_simyr2000_c230601.nc +lnd/clm2/surfdata_esmf/NEON/surfdata_1x1_NEON_${NEONSITE}_hist_2000_78pfts_c240206.nc @@ -1362,249 +1495,102 @@ lnd/clm2/surfdata_map/NEON/surfdata_1x1_NEON_TOOL_hist_78pfts_CMIP6_simyr2000_c2 -lnd/clm2/surfdata_map/landuse.timeseries_0.9x1.25_hist_16pfts_Irrig_CMIP6_simyr1850-2015_c170824.nc -lnd/clm2/surfdata_map/landuse.timeseries_0.9x1.25_hist_16pfts_Irrig_CMIP6_simyr1850-2015_c170824.nc -lnd/clm2/surfdata_map/landuse.timeseries_1.9x2.5_hist_16pfts_Irrig_CMIP6_simyr1850-2015_c170824.nc -lnd/clm2/surfdata_map/landuse.timeseries_1.9x2.5_hist_16pfts_Irrig_CMIP6_simyr1850-2015_c170824.nc -lnd/clm2/surfdata_map/landuse.timeseries_10x15_hist_16pfts_Irrig_CMIP6_simyr1850-2015_c170824.nc -lnd/clm2/surfdata_map/landuse.timeseries_10x15_hist_16pfts_Irrig_CMIP6_simyr1850-2015_c170824.nc -lnd/clm2/surfdata_map/landuse.timeseries_4x5_hist_16pfts_Irrig_CMIP6_simyr1850-2015_c170824.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_48x96_hist_16pfts_Irrig_CMIP6_simyr1850-2015_c190214.nc - - -lnd/clm2/surfdata_map/release-clm5.0.30/landuse.timeseries_ne30np4_SSP5-8.5_78pfts_CMIP6_simyr1850-2100_c200426.nc -lnd/clm2/surfdata_map/release-clm5.0.30/landuse.timeseries_ne30np4.pg3_SSP5-8.5_78pfts_CMIP6_simyr1850-2100_c200426.nc -lnd/clm2/surfdata_map/release-clm5.0.30/landuse.timeseries_ne0np4.ARCTIC.ne30x4_SSP5-8.5_78pfts_CMIP6_simyr1850-2100_c200426.nc - - - -lnd/clm2/surfdata_map/landuse.timeseries_0.9x1.25_hist_78pfts_CMIP6_simyr1850-2015_c170824.nc -lnd/clm2/surfdata_map/landuse.timeseries_1.9x2.5_hist_78pfts_CMIP6_simyr1850-2015_c170824.nc -lnd/clm2/surfdata_map/landuse.timeseries_10x15_hist_78pfts_CMIP6_simyr1850-2015_c170824.nc +lnd/clm2/surfdata_esmf/ctsm5.2.0/landuse.timeseries_0.9x1.25_SSP2-4.5_1850-2100_78pfts_c240216.nc +lnd/clm2/surfdata_esmf/ctsm5.2.0/landuse.timeseries_1.9x2.5_SSP2-4.5_1850-2100_78pfts_c240216.nc + + lnd/clm2/surfdata_map/landuse.timeseries_4x5_hist_78pfts_CMIP6_simyr1850-2015_c170824.nc -lnd/clm2/surfdata_map/landuse.timeseries_48x96_hist_78pfts_CMIP6_simyr1850-2015_c170824.nc + >lnd/clm2/surfdata_esmf/ctsm5.2.0/landuse.timeseries_4x5_SSP2-4.5_1850-2100_78pfts_c240216.nc +lnd/clm2/surfdata_esmf/ctsm5.2.0/landuse.timeseries_10x15_SSP2-4.5_1850-2100_78pfts_c240216.nc + +lnd/clm2/surfdata_esmf/ctsm5.2.0/landuse.timeseries_360x720cru_SSP2-4.5_1850-2100_78pfts_c240216.nc lnd/clm2/surfdata_map/ctsm5.1.dev116/landuse.timeseries_1x1_brazil_hist_78pfts_CMIP6_simyr1850-2015_c230123.nc -lnd/clm2/surfdata_map/landuse.timeseries_1x1_numaIA_hist_78pfts_CMIP6_simyr1850-2015_c170917.nc - -lnd/clm2/surfdata_map/ctsm5.1.dev052/landuse.timeseries_mpasa480_hist_78pfts_CMIP6_simyr1850-2015_c211110.nc -lnd/clm2/surfdata_map/ctsm5.1.dev052/landuse.timeseries_mpasa240_hist_78pfts_CMIP6_simyr1850-2015_c211115.nc -lnd/clm2/surfdata_map/ctsm5.1.dev052/landuse.timeseries_mpasa120_hist_78pfts_CMIP6_simyr1850-2015_c211108.nc -lnd/clm2/surfdata_map/ctsm5.1.dev052/landuse.timeseries_mpasa60_hist_78pfts_CMIP6_simyr1850-2015_c211110.nc -lnd/clm2/surfdata_map/ctsm5.1.dev052/landuse.timeseries_mpasa30_hist_78pfts_CMIP6_simyr1850-2015_c211111.nc -lnd/clm2/surfdata_map/ctsm5.1.dev052/landuse.timeseries_mpasa15_hist_78pfts_CMIP6_simyr1850-2015_c211111.nc - -lnd/clm2/surfdata_map/ctsm5.1.dev120/landuse.timeseries_ne3np4.pg3_SSP5-8.5_78pfts_CMIP6_simyr1850-2100_c230405.nc -lnd/clm2/surfdata_map/ctsm5.1.dev120/landuse.timeseries_ne5np4.pg3_SSP5-8.5_78pfts_CMIP6_simyr1850-2100_c230405.nc -lnd/clm2/surfdata_map/ctsm5.1.dev120/landuse.timeseries_ne16np4.pg3_SSP5-8.5_78pfts_CMIP6_simyr1850-2100_c230405.nc -lnd/clm2/surfdata_map/release-clm5.0.30/landuse.timeseries_ne30np4_SSP5-8.5_78pfts_CMIP6_simyr1850-2100_c200426.nc -lnd/clm2/surfdata_map/release-clm5.0.30/landuse.timeseries_ne30np4.pg2_SSP5-8.5_78pfts_CMIP6_simyr1850-2100_c200426.nc -lnd/clm2/surfdata_map/release-clm5.0.30/landuse.timeseries_ne30np4.pg3_SSP5-8.5_78pfts_CMIP6_simyr1850-2100_c200426.nc -lnd/clm2/surfdata_map/release-clm5.0.30/landuse.timeseries_ne0np4.ARCTICGRIS.ne30x8_SSP5-8.5_78pfts_CMIP6_simyr1850-2100_c200426.nc -lnd/clm2/surfdata_map/release-clm5.0.30/landuse.timeseries_ne0np4.ARCTIC.ne30x4_SSP5-8.5_78pfts_CMIP6_simyr1850-2100_c200426.nc -lnd/clm2/surfdata_map/release-clm5.0.30/landuse.timeseries_ne0np4.CONUS.ne30x8_SSP5-8.5_78pfts_CMIP6_simyr1850-2100_c200426.nc - -lnd/clm2/surfdata_map/release-clm5.0.30/landuse.timeseries_C24_SSP5-8.5_78pfts_CMIP6_simyr1850-2100_c200317.nc +>lnd/clm2/surfdata_esmf/ctsm5.2.0/landuse.timeseries_1x1_brazil_SSP2-4.5_1850-2100_78pfts_c240221.nc + +lnd/clm2/surfdata_esmf/ctsm5.2.0/landuse.timeseries_mpasa120_SSP2-4.5_1850-2100_78pfts_c240216.nc + +lnd/clm2/surfdata_esmf/ctsm5.2.0/landuse.timeseries_ne3np4.pg3_SSP2-4.5_1850-2100_78pfts_c240216.nc +lnd/clm2/surfdata_esmf/ctsm5.2.0/landuse.timeseries_ne16np4.pg3_SSP2-4.5_1850-2100_78pfts_c240216.nc +lnd/clm2/surfdata_esmf/ctsm5.2.0/landuse.timeseries_ne30np4.pg3_SSP2-4.5_1850-2100_78pfts_c240216.nc + lnd/clm2/surfdata_map/release-clm5.0.30/landuse.timeseries_C96_SSP5-8.5_78pfts_CMIP6_simyr1850-2100_c200317.nc +>lnd/clm2/surfdata_esmf/ctsm5.2.0/landuse.timeseries_C96_SSP2-4.5_1850-2100_78pfts_c240216.nc lnd/clm2/surfdata_map/landuse.timeseries_1x1_smallvilleIA_hist_78pfts_simyr1850-1855_c160127.nc +>lnd/clm2/surfdata_esmf/ctsm5.2.0/landuse.timeseries_1x1_smallvilleIA_SSP2-4.5_1850-1855_78pfts_c240221.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_0.9x1.25_SSP5-8.5_78pfts_CMIP6_simyr1850-2100_c190214.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_1.9x2.5_SSP5-8.5_78pfts_CMIP6_simyr1850-2100_c190228.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_10x15_SSP5-8.5_78pfts_CMIP6_simyr1850-2100_c190228.nc -lnd/clm2/surfdata_map/release-clm5.0.30/landuse.timeseries_C24_SSP5-8.5_78pfts_CMIP6_simyr1850-2100_c200317.nc -lnd/clm2/surfdata_map/release-clm5.0.30/landuse.timeseries_C96_SSP5-8.5_78pfts_CMIP6_simyr1850-2100_c200317.nc - -lnd/clm2/surfdata_map/ctsm5.1.dev120/landuse.timeseries_ne3np4.pg3_SSP5-8.5_78pfts_CMIP6_simyr1850-2100_c230405.nc -lnd/clm2/surfdata_map/ctsm5.1.dev120/landuse.timeseries_ne5np4.pg3_SSP5-8.5_78pfts_CMIP6_simyr1850-2100_c230405.nc -lnd/clm2/surfdata_map/ctsm5.1.dev120/landuse.timeseries_ne16np4.pg3_SSP5-8.5_78pfts_CMIP6_simyr1850-2100_c230405.nc -lnd/clm2/surfdata_map/release-clm5.0.30/landuse.timeseries_ne30np4_SSP5-8.5_78pfts_CMIP6_simyr1850-2100_c200426.nc -lnd/clm2/surfdata_map/release-clm5.0.30/landuse.timeseries_ne30np4.pg2_SSP5-8.5_78pfts_CMIP6_simyr1850-2100_c200426.nc -lnd/clm2/surfdata_map/release-clm5.0.30/landuse.timeseries_ne30np4.pg3_SSP5-8.5_78pfts_CMIP6_simyr1850-2100_c200426.nc -lnd/clm2/surfdata_map/release-clm5.0.30/landuse.timeseries_ne0np4.ARCTICGRIS.ne30x8_SSP5-8.5_78pfts_CMIP6_simyr1850-2100_c200426.nc -lnd/clm2/surfdata_map/release-clm5.0.30/landuse.timeseries_ne0np4.ARCTIC.ne30x4_SSP5-8.5_78pfts_CMIP6_simyr1850-2100_c200426.nc -lnd/clm2/surfdata_map/release-clm5.0.30/landuse.timeseries_ne0np4.CONUS.ne30x8_SSP5-8.5_78pfts_CMIP6_simyr1850-2100_c200426.nc - lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_0.9x1.25_SSP1-2.6_78pfts_CMIP6_simyr1850-2100_c190214.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_1.9x2.5_SSP1-2.6_78pfts_CMIP6_simyr1850-2100_c190228.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_10x15_SSP1-2.6_78pfts_CMIP6_simyr1850-2100_c190228.nc + >lnd/clm2/surfdata_esmf/ctsm5.2.0/landuse.timeseries_0.9x1.25_SSP1-2.6_1850-2100_78pfts_c240216.nc lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_0.9x1.25_SSP2-4.5_78pfts_CMIP6_simyr1850-2100_c190214.nc + >lnd/clm2/surfdata_esmf/ctsm5.2.0/landuse.timeseries_0.9x1.25_SSP2-4.5_1850-2100_78pfts_c240216.nc lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_1.9x2.5_SSP2-4.5_78pfts_CMIP6_simyr1850-2100_c190228.nc + >lnd/clm2/surfdata_esmf/ctsm5.2.0/landuse.timeseries_1.9x2.5_SSP2-4.5_1850-2100_78pfts_c240216.nc + + +lnd/clm2/surfdata_esmf/ctsm5.2.0/landuse.timeseries_4x5_SSP2-4.5_1850-2100_78pfts_c240216.nc lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_10x15_SSP2-4.5_78pfts_CMIP6_simyr1850-2100_c190228.nc + >lnd/clm2/surfdata_esmf/ctsm5.2.0/landuse.timeseries_10x15_SSP2-4.5_1850-2100_78pfts_c240216.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_0.9x1.25_SSP3-7.0_78pfts_CMIP6_simyr1850-2100_c190214.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_1.9x2.5_SSP3-7.0_78pfts_CMIP6_simyr1850-2100_c190228.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_10x15_SSP3-7.0_78pfts_CMIP6_simyr1850-2100_c190228.nc +lnd/clm2/surfdata_esmf/ctsm5.2.0/landuse.timeseries_360x720cru_SSP2-4.5_1850-2100_78pfts_c240216.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_0.9x1.25_SSP4-3.4_78pfts_CMIP6_simyr1850-2100_c190214.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_1.9x2.5_SSP4-3.4_78pfts_CMIP6_simyr1850-2100_c190228.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_10x15_SSP4-3.4_78pfts_CMIP6_simyr1850-2100_c190228.nc +lnd/clm2/surfdata_esmf/ctsm5.2.0/landuse.timeseries_1x1_brazil_SSP2-4.5_1850-2100_78pfts_c240221.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_0.9x1.25_SSP1-1.9_78pfts_CMIP6_simyr1850-2100_c190214.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_1.9x2.5_SSP1-1.9_78pfts_CMIP6_simyr1850-2100_c190228.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_10x15_SSP1-1.9_78pfts_CMIP6_simyr1850-2100_c190228.nc - - -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_0.9x1.25_SSP4-6.0_78pfts_CMIP6_simyr1850-2100_c190214.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_1.9x2.5_SSP4-6.0_78pfts_CMIP6_simyr1850-2100_c190228.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_10x15_SSP4-6.0_78pfts_CMIP6_simyr1850-2100_c190228.nc - - -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_0.9x1.25_SSP5-3.4_78pfts_CMIP6_simyr1850-2100_c190214.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_1.9x2.5_SSP5-3.4_78pfts_CMIP6_simyr1850-2100_c190228.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_10x15_SSP5-3.4_78pfts_CMIP6_simyr1850-2100_c190228.nc +lnd/clm2/surfdata_esmf/ctsm5.2.0/landuse.timeseries_mpasa120_SSP2-4.5_1850-2100_78pfts_c240216.nc - +lnd/clm2/surfdata_esmf/ctsm5.2.0/landuse.timeseries_ne3np4.pg3_SSP2-4.5_1850-2100_78pfts_c240216.nc +lnd/clm2/surfdata_esmf/ctsm5.2.0/landuse.timeseries_ne16np4.pg3_SSP2-4.5_1850-2100_78pfts_c240216.nc +lnd/clm2/surfdata_esmf/ctsm5.2.0/landuse.timeseries_ne30np4.pg3_SSP2-4.5_1850-2100_78pfts_c240216.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_0.9x1.25_SSP5-8.5_16pfts_Irrig_CMIP6_simyr1850-2100_c190214.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_1.9x2.5_SSP5-8.5_16pfts_Irrig_CMIP6_simyr1850-2100_c190228.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_10x15_SSP5-8.5_16pfts_Irrig_CMIP6_simyr1850-2100_c190228.nc - - -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_0.9x1.25_SSP1-2.6_16pfts_Irrig_CMIP6_simyr1850-2100_c190214.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_1.9x2.5_SSP1-2.6_16pfts_Irrig_CMIP6_simyr1850-2100_c190228.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_10x15_SSP1-2.6_16pfts_Irrig_CMIP6_simyr1850-2100_c190228.nc - - -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_0.9x1.25_SSP2-4.5_16pfts_Irrig_CMIP6_simyr1850-2100_c190214.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_1.9x2.5_SSP2-4.5_16pfts_Irrig_CMIP6_simyr1850-2100_c190228.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_10x15_SSP2-4.5_16pfts_Irrig_CMIP6_simyr1850-2100_c190228.nc +lnd/clm2/surfdata_esmf/ctsm5.2.0/landuse.timeseries_C96_SSP2-4.5_1850-2100_78pfts_c240216.nc lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_0.9x1.25_SSP3-7.0_16pfts_Irrig_CMIP6_simyr1850-2100_c190214.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_1.9x2.5_SSP3-7.0_16pfts_Irrig_CMIP6_simyr1850-2100_c190228.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_10x15_SSP3-7.0_16pfts_Irrig_CMIP6_simyr1850-2100_c190228.nc +>lnd/clm2/surfdata_esmf/ctsm5.2.0/landuse.timeseries_0.9x1.25_SSP3-7.0_1850-2100_78pfts_c240216.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_0.9x1.25_SSP4-3.4_16pfts_Irrig_CMIP6_simyr1850-2100_c190214.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_1.9x2.5_SSP4-3.4_16pfts_Irrig_CMIP6_simyr1850-2100_c190228.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_10x15_SSP4-3.4_16pfts_Irrig_CMIP6_simyr1850-2100_c190228.nc + +lnd/clm2/surfdata_esmf/ctsm5.2.0/landuse.timeseries_0.9x1.25_SSP4-6.0_1850-2100_78pfts_c240216.nc + + +lnd/clm2/surfdata_esmf/ctsm5.2.0/landuse.timeseries_0.9x1.25_SSP5-8.5_1850-2100_78pfts_c240216.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_0.9x1.25_SSP1-1.9_16pfts_Irrig_CMIP6_simyr1850-2100_c190214.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_1.9x2.5_SSP1-1.9_16pfts_Irrig_CMIP6_simyr1850-2100_c190228.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_10x15_SSP1-1.9_16pfts_Irrig_CMIP6_simyr1850-2100_c190228.nc + - -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_0.9x1.25_SSP4-6.0_16pfts_Irrig_CMIP6_simyr1850-2100_c190214.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_1.9x2.5_SSP4-6.0_16pfts_Irrig_CMIP6_simyr1850-2100_c190228.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_10x15_SSP4-6.0_16pfts_Irrig_CMIP6_simyr1850-2100_c190228.nc + + -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_0.9x1.25_SSP5-3.4_16pfts_Irrig_CMIP6_simyr1850-2100_c190214.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_1.9x2.5_SSP5-3.4_16pfts_Irrig_CMIP6_simyr1850-2100_c190228.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_10x15_SSP5-3.4_16pfts_Irrig_CMIP6_simyr1850-2100_c190228.nc + @@ -1616,27 +1602,22 @@ use_crop=".true.">lnd/clm2/surfdata_map/ctsm5.1.dev052/landuse.timeseries_mpasa1 >lnd/clm2/surfdata_map/fates-sci.1.68.3_api.31.0.0_tools.1.0.1/LUH2_states_transitions_management.timeseries_4x5_hist_simyr1850-2015_c231101.nc -.true. -.true. .false. +.true. +.false. 0.0117d00 0.0006d00 0.83d-06 - -0.015d00 -0.015d00 -0.015d00 + +0.015d00 -100.d00 -100.d00 +100.d00 20.d00 -1.d00 -1.d00 -1.d00 +1.d00 @@ -1647,7 +1628,7 @@ use_crop=".true.">lnd/clm2/surfdata_map/ctsm5.1.dev052/landuse.timeseries_mpasa1 lnd/clm2/snicardata/snicar_optics_480bnd_c012422.nc lnd/clm2/snicardata/snicar_optics_5bnd_c013122.nc -hexagonal_plate +hexagonal_plate sphere sphere @@ -1661,17 +1642,9 @@ use_crop=".true.">lnd/clm2/surfdata_map/ctsm5.1.dev052/landuse.timeseries_mpasa1 .false. -2015 -2101 -2015 - -2015 -2101 -2015 - -2015 -2101 -2015 +2015 +2101 +2015 2018 2018 @@ -1694,49 +1667,23 @@ use_crop=".true.">lnd/clm2/surfdata_map/ctsm5.1.dev052/landuse.timeseries_mpasa1 2000 2000 -lnd/clm2/ndepdata/fndep_clm_hist_b.e21.BWHIST.f09_g17.CMIP6-historical-WACCM.ensmean_1849-2015_monthly_0.9x1.25_c180926.nc -lnd/clm2/ndepdata/fndep_clm_hist_b.e21.BWHIST.f09_g17.CMIP6-historical-WACCM.ensmean_1849-2015_monthly_0.9x1.25_c180926.nc -lnd/clm2/ndepdata/fndep_clm_hist_b.e21.BWHIST.f09_g17.CMIP6-historical-WACCM.ensmean_1849-2015_monthly_0.9x1.25_c180926.nc +lnd/clm2/ndepdata/fndep_clm_hist_b.e21.BWHIST.f09_g17.CMIP6-historical-WACCM.ensmean_1849-2015_monthly_0.9x1.25_c180926.nc share/meshes/fv1.9x2.5_141008_ESMFmesh_c20191001.nc share/meshes/fv0.9x1.25_141008_polemod_ESMFmesh.nc -lnd/clm2/ndepdata/fndep_clm_f09_g17.CMIP6-SSP5-8.5-WACCM_1849-2101_monthly_c191007.nc -lnd/clm2/ndepdata/fndep_clm_f09_g17.CMIP6-SSP1-2.6-WACCM_1849-2101_monthly_c191007.nc -lnd/clm2/ndepdata/fndep_clm_f09_g17.CMIP6-SSP2-4.5-WACCM_1849-2101_monthly_c191007.nc -lnd/clm2/ndepdata/fndep_clm_SSP370_b.e21.BWSSP370cmip6.f09_g17.CMIP6-SSP3-7.0-WACCM.002_1849-2101_monthly_0.9x1.25_c211216.nc -lnd/clm2/ndepdata/fndep_clm_f09_g17.CMIP6-SSP5-8.5-WACCM_1849-2101_monthly_c191007.nc -lnd/clm2/ndepdata/fndep_clm_f09_g17.CMIP6-SSP1-2.6-WACCM_1849-2101_monthly_c191007.nc -lnd/clm2/ndepdata/fndep_clm_f09_g17.CMIP6-SSP2-4.5-WACCM_1849-2101_monthly_c191007.nc -lnd/clm2/ndepdata/fndep_clm_SSP370_b.e21.BWSSP370cmip6.f09_g17.CMIP6-SSP3-7.0-WACCM.002_1849-2101_monthly_0.9x1.25_c211216.nc - -lnd/clm2/ndepdata/fndep_clm_f09_g17.CMIP6-SSP5-8.5-WACCM_1849-2101_monthly_c191007.nc -lnd/clm2/ndepdata/fndep_clm_f09_g17.CMIP6-SSP1-2.6-WACCM_1849-2101_monthly_c191007.nc -lnd/clm2/ndepdata/fndep_clm_f09_g17.CMIP6-SSP2-4.5-WACCM_1849-2101_monthly_c191007.nc -lnd/clm2/ndepdata/fndep_clm_SSP370_b.e21.BWSSP370cmip6.f09_g17.CMIP6-SSP3-7.0-WACCM.002_1849-2101_monthly_0.9x1.25_c211216.nc - -cycle -NDEP_month - -cycle -NDEP_month - -cycle -NDEP_month +cycle +NDEP_month bilinear @@ -1793,9 +1740,9 @@ use_crop=".true.">lnd/clm2/surfdata_map/ctsm5.1.dev052/landuse.timeseries_mpasa1 none none 106x174 -94x192 +360x720 94x192 -360x720 +94x192 none none none @@ -1828,17 +1775,9 @@ use_crop=".true.">lnd/clm2/surfdata_map/ctsm5.1.dev052/landuse.timeseries_mpasa1 nn -2015 -2100 -2015 - -2015 -2100 -2015 - -2015 -2100 -2015 +2015 +2100 +2015 2018 2018 @@ -1939,17 +1878,9 @@ use_crop=".true.">lnd/clm2/surfdata_map/ctsm5.1.dev052/landuse.timeseries_mpasa1 nn -2015 -2106 -2015 - -2015 -2106 -2015 - -2015 -2106 -2015 +2015 +2106 +2015 2018 2018 @@ -1975,19 +1906,16 @@ use_crop=".true.">lnd/clm2/surfdata_map/ctsm5.1.dev052/landuse.timeseries_mpasa1 1850 2106 +lnd/clm2/urbandata/CTSM52_tbuildmax_OlesonFeddema_2020_0.9x1.25_simyr1849-2106_c200605.nc lnd/clm2/urbandata/CLM50_tbuildmax_Oleson_2016_0.9x1.25_simyr1849-2106_c160923.nc -lnd/clm2/urbandata/CLM50_tbuildmax_Oleson_2016_0.9x1_ESMFmesh_cdf5_100621.nc - +>lnd/clm2/urbandata/CTSM52_tbuildmax_OlesonFeddema_2020_0.9x1.25_simyr1849-2106_c200605.nc lnd/clm2/urbandata/CLM50_tbuildmax_Oleson_2016_0.9x1.25_simyr1849-2106_c160923.nc -lnd/clm2/urbandata/CLM50_tbuildmax_Oleson_2016_0.9x1_ESMFmesh_cdf5_100621.nc - lnd/clm2/urbandata/CLM45_tbuildmax_Oleson_2016_0.9x1.25_simyr1849-2106_c160923.nc -lnd/clm2/urbandata/CLM50_tbuildmax_Oleson_2016_0.9x1_ESMFmesh_cdf5_100621.nc nn @@ -2005,6 +1933,8 @@ use_crop=".true.">lnd/clm2/surfdata_map/ctsm5.1.dev052/landuse.timeseries_mpasa1 .false. +.true. + .false. .true. @@ -2027,724 +1957,6 @@ use_crop=".true.">lnd/clm2/surfdata_map/ctsm5.1.dev052/landuse.timeseries_mpasa1 35 - - - - - - -lnd/clm2/mappingdata/maps/1x1_asphaltjungleNJ/map_0.125x0.125_nomask_to_1x1_asphaltjungleNJ_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1x1_asphaltjungleNJ/map_0.5x0.5_nomask_to_1x1_asphaltjungleNJ_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1x1_asphaltjungleNJ/map_0.25x0.25_nomask_to_1x1_asphaltjungleNJ_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/1x1_asphaltjungleNJ/map_3x3min_nomask_to_1x1_asphaltjungleNJ_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/1x1_asphaltjungleNJ/map_10x10min_nomask_to_1x1_asphaltjungleNJ_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1x1_asphaltjungleNJ/map_5x5min_nomask_to_1x1_asphaltjungleNJ_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/1x1_asphaltjungleNJ/map_0.9x1.25_nomask_to_1x1_asphaltjungleNJ_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1x1_asphaltjungleNJ/map_1km-merge-10min_HYDRO1K-merge-nomask_to_1x1_asphaltjungleNJ_nomask_aave_da_c130403.nc - - - -lnd/clm2/mappingdata/maps/1x1_brazil/map_0.125x0.125_nomask_to_1x1_brazil_nomask_aave_da_c211212.nc -lnd/clm2/mappingdata/maps/1x1_brazil/map_0.5x0.5_nomask_to_1x1_brazil_nomask_aave_da_c211212.nc -lnd/clm2/mappingdata/maps/1x1_brazil/map_0.25x0.25_nomask_to_1x1_brazil_nomask_aave_da_c211212.nc -lnd/clm2/mappingdata/maps/1x1_brazil/map_3x3min_nomask_to_1x1_brazil_nomask_aave_da_c211212.nc -lnd/clm2/mappingdata/maps/1x1_brazil/map_10x10min_nomask_to_1x1_brazil_nomask_aave_da_c211212.nc -lnd/clm2/mappingdata/maps/1x1_brazil/map_5x5min_nomask_to_1x1_brazil_nomask_aave_da_c211212.nc -lnd/clm2/mappingdata/maps/1x1_brazil/map_0.9x1.25_nomask_to_1x1_brazil_nomask_aave_da_c211212.nc -lnd/clm2/mappingdata/maps/1x1_brazil/map_1km-merge-10min_HYDRO1K-merge-nomask_to_1x1_brazil_nomask_aave_da_c211212.nc - - - -lnd/clm2/mappingdata/maps/1x1_mexicocityMEX/map_0.125x0.125_nomask_to_1x1_mexicocityMEX_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1x1_mexicocityMEX/map_0.5x0.5_nomask_to_1x1_mexicocityMEX_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1x1_mexicocityMEX/map_0.25x0.25_nomask_to_1x1_mexicocityMEX_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/1x1_mexicocityMEX/map_3x3min_nomask_to_1x1_mexicocityMEX_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/1x1_mexicocityMEX/map_10x10min_nomask_to_1x1_mexicocityMEX_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1x1_mexicocityMEX/map_5x5min_nomask_to_1x1_mexicocityMEX_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/1x1_mexicocityMEX/map_0.9x1.25_nomask_to_1x1_mexicocityMEX_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1x1_mexicocityMEX/map_1km-merge-10min_HYDRO1K-merge-nomask_to_1x1_mexicocityMEX_nomask_aave_da_c130403.nc - - - -lnd/clm2/mappingdata/maps/1x1_numaIA/map_0.125x0.125_nomask_to_1x1_numaIA_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1x1_numaIA/map_0.5x0.5_nomask_to_1x1_numaIA_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1x1_numaIA/map_0.25x0.25_nomask_to_1x1_numaIA_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/1x1_numaIA/map_3x3min_nomask_to_1x1_numaIA_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/1x1_numaIA/map_10x10min_nomask_to_1x1_numaIA_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1x1_numaIA/map_5x5min_nomask_to_1x1_numaIA_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/1x1_numaIA/map_0.9x1.25_nomask_to_1x1_numaIA_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1x1_numaIA/map_1km-merge-10min_HYDRO1K-merge-nomask_to_1x1_numaIA_nomask_aave_da_c130403.nc - - - -lnd/clm2/mappingdata/maps/1x1_smallvilleIA/map_0.125x0.125_nomask_to_1x1_smallvilleIA_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1x1_smallvilleIA/map_0.25x0.25_nomask_to_1x1_smallvilleIA_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/1x1_smallvilleIA/map_0.5x0.5_nomask_to_1x1_smallvilleIA_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1x1_smallvilleIA/map_10x10min_nomask_to_1x1_smallvilleIA_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1x1_smallvilleIA/map_3x3min_nomask_to_1x1_smallvilleIA_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/1x1_smallvilleIA/map_5x5min_nomask_to_1x1_smallvilleIA_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/1x1_smallvilleIA/map_0.9x1.25_nomask_to_1x1_smallvilleIA_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1x1_smallvilleIA/map_1km-merge-10min_HYDRO1K-merge-nomask_to_1x1_smallvilleIA_nomask_aave_da_c130403.nc - - - -lnd/clm2/mappingdata/maps/1x1_urbanc_alpha/map_0.125x0.125_nomask_to_1x1_urbanc_alpha_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1x1_urbanc_alpha/map_0.25x0.25_nomask_to_1x1_urbanc_alpha_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/1x1_urbanc_alpha/map_0.5x0.5_nomask_to_1x1_urbanc_alpha_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1x1_urbanc_alpha/map_10x10min_nomask_to_1x1_urbanc_alpha_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1x1_urbanc_alpha/map_3x3min_nomask_to_1x1_urbanc_alpha_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/1x1_urbanc_alpha/map_5x5min_nomask_to_1x1_urbanc_alpha_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/1x1_urbanc_alpha/map_0.9x1.25_nomask_to_1x1_urbanc_alpha_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1x1_urbanc_alpha/map_1km-merge-10min_HYDRO1K-merge-nomask_to_1x1_urbanc_alpha_nomask_aave_da_c130403.nc - - - -lnd/clm2/mappingdata/maps/1x1_vancouverCAN/map_0.125x0.125_nomask_to_1x1_vancouverCAN_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1x1_vancouverCAN/map_0.25x0.25_nomask_to_1x1_vancouverCAN_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/1x1_vancouverCAN/map_0.5x0.5_nomask_to_1x1_vancouverCAN_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1x1_vancouverCAN/map_10x10min_nomask_to_1x1_vancouverCAN_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1x1_vancouverCAN/map_3x3min_nomask_to_1x1_vancouverCAN_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/1x1_vancouverCAN/map_5x5min_nomask_to_1x1_vancouverCAN_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/1x1_vancouverCAN/map_0.9x1.25_nomask_to_1x1_vancouverCAN_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1x1_vancouverCAN/map_1km-merge-10min_HYDRO1K-merge-nomask_to_1x1_vancouverCAN_nomask_aave_da_c130403.nc - - - -lnd/clm2/mappingdata/maps/0.47x0.63/map_0.125x0.125_nomask_to_0.47x0.63_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/0.47x0.63/map_0.5x0.5_nomask_to_0.47x0.63_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/0.47x0.63/map_0.25x0.25_nomask_to_0.47x0.63_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/0.47x0.63/map_10x10min_nomask_to_0.47x0.63_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/0.47x0.63/map_1km-merge-10min_HYDRO1K-merge-nomask_to_0.47x0.63_nomask_aave_da_c170914.nc -lnd/clm2/mappingdata/maps/0.47x0.63/map_3x3min_nomask_to_0.47x0.63_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/0.47x0.63/map_5x5min_nomask_to_0.47x0.63_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/0.47x0.63/map_0.9x1.25_nomask_to_0.47x0.63_nomask_aave_da_c200206.nc - - - -lnd/clm2/mappingdata/maps/0.9x1.25/map_0.125x0.125_nomask_to_0.9x1.25_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/0.9x1.25/map_0.5x0.5_nomask_to_0.9x1.25_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/0.9x1.25/map_0.25x0.25_nomask_to_0.9x1.25_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/0.9x1.25/map_10x10min_nomask_to_0.9x1.25_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/0.9x1.25/map_5x5min_nomask_to_0.9x1.25_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/0.9x1.25/map_3x3min_nomask_to_0.9x1.25_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/0.9x1.25/map_0.9x1.25_nomask_to_0.9x1.25_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/0.9x1.25/map_1km-merge-10min_HYDRO1K-merge-nomask_to_0.9x1.25_nomask_aave_da_c130405.nc - -lnd/clm2/mappingdata/maps/1.9x2.5/map_0.125x0.125_nomask_to_1.9x2.5_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1.9x2.5/map_0.5x0.5_nomask_to_1.9x2.5_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1.9x2.5/map_0.25x0.25_nomask_to_1.9x2.5_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/1.9x2.5/map_10x10min_nomask_to_1.9x2.5_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1.9x2.5/map_5x5min_nomask_to_1.9x2.5_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/1.9x2.5/map_3x3min_nomask_to_1.9x2.5_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/1.9x2.5/map_0.9x1.25_nomask_to_1.9x2.5_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1.9x2.5/map_1km-merge-10min_HYDRO1K-merge-nomask_to_1.9x2.5_nomask_aave_da_c130405.nc - - -lnd/clm2/mappingdata/maps/10x15/map_0.125x0.125_nomask_to_10x15_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/10x15/map_0.5x0.5_nomask_to_10x15_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/10x15/map_0.25x0.25_nomask_to_10x15_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/10x15/map_10x10min_nomask_to_10x15_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/10x15/map_5x5min_nomask_to_10x15_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/10x15/map_3x3min_nomask_to_10x15_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/10x15/map_0.9x1.25_nomask_to_10x15_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/10x15/map_1km-merge-10min_HYDRO1K-merge-nomask_to_10x15_nomask_aave_da_c130411.nc - - - - - -lnd/clm2/mappingdata/maps/360x720/map_0.125x0.125_nomask_to_360x720cru_nomask_aave_da_c210823.nc -lnd/clm2/mappingdata/maps/360x720/map_0.5x0.5_nomask_to_360x720_nomask_aave_da_c120830.nc -lnd/clm2/mappingdata/maps/360x720/map_0.25x0.25_nomask_to_360x720cru_nomask_aave_da_c210823.nc -lnd/clm2/mappingdata/maps/360x720/map_3x3min_nomask_to_360x720cru_nomask_aave_da_c210823.nc -lnd/clm2/mappingdata/maps/360x720/map_10x10min_nomask_to_360x720_nomask_aave_da_c120830.nc -lnd/clm2/mappingdata/maps/360x720/map_5x5min_nomask_to_360x720_nomask_aave_da_c120830.nc -lnd/clm2/mappingdata/maps/360x720/map_0.9x1.25_nomask_to_360x720cru_nomask_aave_da_c210823.nc -lnd/clm2/mappingdata/maps/360x720/map_1km-merge-10min_HYDRO1K-merge-nomask_to_360x720_nomask_aave_da_c130403.nc - - - -lnd/clm2/mappingdata/maps/512x1024/map_0.125x0.125_nomask_to_512x1024_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/512x1024/map_0.5x0.5_nomask_to_512x1024_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/512x1024/map_0.25x0.25_nomask_to_512x1024_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/512x1024/map_10x10min_nomask_to_512x1024_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/512x1024/map_5x5min_nomask_to_512x1024_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/512x1024/map_3x3min_nomask_to_512x1024_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/512x1024/map_0.9x1.25_nomask_to_512x1024_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/512x1024/map_1km-merge-10min_HYDRO1K-merge-nomask_to_512x1024_nomask_aave_da_c130403.nc - - -lnd/clm2/mappingdata/maps/128x256/map_0.125x0.125_nomask_to_128x256_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/128x256/map_0.5x0.5_nomask_to_128x256_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/128x256/map_0.25x0.25_nomask_to_128x256_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/128x256/map_10x10min_nomask_to_128x256_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/128x256/map_5x5min_nomask_to_128x256_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/128x256/map_3x3min_nomask_to_128x256_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/128x256/map_0.9x1.25_nomask_to_128x256_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/128x256/map_1km-merge-10min_HYDRO1K-merge-nomask_to_128x256_nomask_aave_da_c130403.nc - - -lnd/clm2/mappingdata/maps/64x128/map_0.125x0.125_nomask_to_64x128_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/64x128/map_0.5x0.5_nomask_to_64x128_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/64x128/map_0.25x0.25_nomask_to_64x128_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/64x128/map_10x10min_nomask_to_64x128_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/64x128/map_5x5min_nomask_to_64x128_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/64x128/map_3x3min_nomask_to_64x128_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/64x128/map_0.9x1.25_nomask_to_64x128_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/64x128/map_1km-merge-10min_HYDRO1K-merge-nomask_to_64x128_nomask_aave_da_c130403.nc - -lnd/clm2/mappingdata/maps/48x96/map_0.125x0.125_nomask_to_48x96_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/48x96/map_0.5x0.5_nomask_to_48x96_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/48x96/map_0.25x0.25_nomask_to_48x96_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/48x96/map_10x10min_nomask_to_48x96_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/48x96/map_5x5min_nomask_to_48x96_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/48x96/map_3x3min_nomask_to_48x96_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/48x96/map_0.9x1.25_nomask_to_48x96_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/48x96/map_1km-merge-10min_HYDRO1K-merge-nomask_to_48x96_nomask_aave_da_c130405.nc - -lnd/clm2/mappingdata/maps/4x5/map_0.125x0.125_nomask_to_4x5_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/4x5/map_0.5x0.5_nomask_to_4x5_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/4x5/map_0.25x0.25_nomask_to_4x5_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/4x5/map_10x10min_nomask_to_4x5_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/4x5/map_5x5min_nomask_to_4x5_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/4x5/map_3x3min_nomask_to_4x5_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/4x5/map_0.9x1.25_nomask_to_4x5_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/4x5/map_1km-merge-10min_HYDRO1K-merge-nomask_to_4x5_nomask_aave_da_c130411.nc - -lnd/clm2/mappingdata/maps/0.23x0.31/map_0.125x0.125_nomask_to_0.23x0.31_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/0.23x0.31/map_0.5x0.5_nomask_to_0.23x0.31_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/0.23x0.31/map_0.25x0.25_nomask_to_0.23x0.31_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/0.23x0.31/map_10x10min_nomask_to_0.23x0.31_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/0.23x0.31/map_5x5min_nomask_to_0.23x0.31_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/0.23x0.31/map_3x3min_nomask_to_0.23x0.31_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/0.23x0.31/map_0.9x1.25_nomask_to_0.23x0.31_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/0.23x0.31/map_1km-merge-10min_HYDRO1K-merge-nomask_to_0.23x0.31_nomask_aave_da_c130405.nc - - -lnd/clm2/mappingdata/maps/2.5x3.33/map_0.125x0.125_nomask_to_2.5x3.33_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/2.5x3.33/map_0.5x0.5_nomask_to_2.5x3.33_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/2.5x3.33/map_0.25x0.25_nomask_to_2.5x3.33_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/2.5x3.33/map_10x10min_nomask_to_2.5x3.33_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/2.5x3.33/map_5x5min_nomask_to_2.5x3.33_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/2.5x3.33/map_3x3min_nomask_to_2.5x3.33_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/2.5x3.33/map_0.9x1.25_nomask_to_2.5x3.33_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/2.5x3.33/map_1km-merge-10min_HYDRO1K-merge-nomask_to_2.5x3.33_nomask_aave_da_c130405.nc - - - -lnd/clm2/mappingdata/maps/0.5x0.5/map_0.125x0.125_nomask_to_0.5x0.5_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/0.5x0.5/map_0.5x0.5_nomask_to_0.5x0.5_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/0.5x0.5/map_10x10min_nomask_to_0.5x0.5_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/0.5x0.5/map_0.25x0.25_nomask_to_0.5x0.5_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/0.5x0.5/map_3x3min_nomask_to_0.5x0.5_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/0.5x0.5/map_5x5min_nomask_to_0.5x0.5_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/0.5x0.5/map_0.9x1.25_nomask_to_0.5x0.5_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/0.5x0.5/map_1km-merge-10min_HYDRO1K-merge-nomask_to_0.5x0.5_nomask_aave_da_c130405.nc - - -lnd/clm2/mappingdata/maps/ne4np4/map_0.125x0.125_nomask_to_ne4np4_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/ne4np4/map_0.5x0.5_nomask_to_ne4np4_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/ne4np4/map_0.25x0.25_nomask_to_ne4np4_nomask_aave_da_c200309.nc - -lnd/clm2/mappingdata/maps/C24/map_0.5x0.5_TO_C24_aave.181018.nc -lnd/clm2/mappingdata/maps/C24/map_10x10min_nomask_to_C24_nomask_aave_da_c181018.nc -lnd/clm2/mappingdata/maps/C24/map_5x5min_nomask_to_C24_nomask_aave_da_c181018.nc -lnd/clm2/mappingdata/maps/C24/map_1km-merge-10min_HYDRO1K-merge-nomask_to_C24_nomask_aave_da_c181018.nc -lnd/clm2/mappingdata/maps/C24/map_C24_nomask_to_0.5x0.5_nomask_aave_da_c181018.nc - - - -lnd/clm2/mappingdata/maps/C48/map_0.5x0.5_TO_C48_aave.181018.nc -lnd/clm2/mappingdata/maps/C48/map_10x10min_nomask_to_C48_nomask_aave_da_c181018.nc -lnd/clm2/mappingdata/maps/C48/map_5x5min_nomask_to_C48_nomask_aave_da_c181018.nc -lnd/clm2/mappingdata/maps/C48/map_1km-merge-10min_HYDRO1K-merge-nomask_to_C48_nomask_aave_da_c181018.nc -lnd/clm2/mappingdata/maps/C48/map_C48_nomask_to_0.5x0.5_nomask_aave_da_c181018.nc - - - -lnd/clm2/mappingdata/maps/C96/map_0.5x0.5_TO_C96_aave.181018.nc -lnd/clm2/mappingdata/maps/C96/map_10x10min_nomask_to_C96_nomask_aave_da_c181018.nc -lnd/clm2/mappingdata/maps/C96/map_5x5min_nomask_to_C96_nomask_aave_da_c181018.nc -lnd/clm2/mappingdata/maps/C96/map_1km-merge-10min_HYDRO1K-merge-nomask_to_C96_nomask_aave_da_c181018.nc -lnd/clm2/mappingdata/maps/C96/map_C96_nomask_to_0.5x0.5_nomask_aave_da_c181018.nc - - - -lnd/clm2/mappingdata/maps/C192/map_0.5x0.5_TO_C192_aave.181018.nc -lnd/clm2/mappingdata/maps/C192/map_10x10min_nomask_to_C192_nomask_aave_da_c181018.nc -lnd/clm2/mappingdata/maps/C192/map_5x5min_nomask_to_C192_nomask_aave_da_c181018.nc -lnd/clm2/mappingdata/maps/C192/map_1km-merge-10min_HYDRO1K-merge-nomask_to_C192_nomask_aave_da_c181018.nc -lnd/clm2/mappingdata/maps/C192/map_C192_nomask_to_0.5x0.5_nomask_aave_da_c181018.nc - - - -lnd/clm2/mappingdata/maps/C384/map_0.5x0.5_TO_C384_aave.181018.nc -lnd/clm2/mappingdata/maps/C384/map_10x10min_nomask_to_C384_nomask_aave_da_c181018.nc -lnd/clm2/mappingdata/maps/C384/map_5x5min_nomask_to_C384_nomask_aave_da_c181018.nc -lnd/clm2/mappingdata/maps/C384/map_1km-merge-10min_HYDRO1K-merge-nomask_to_C384_nomask_aave_da_c181018.nc -lnd/clm2/mappingdata/maps/C384/map_C384_nomask_to_0.5x0.5_nomask_aave_da_c181018.nc - - -lnd/clm2/mappingdata/maps/ne4np4/map_10x10min_nomask_to_ne4np4_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/ne4np4/map_5x5min_nomask_to_ne4np4_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/ne4np4/map_3x3min_nomask_to_ne4np4_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/ne4np4/map_0.9x1.25_nomask_to_ne4np4_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/ne4np4/map_1km-merge-10min_HYDRO1K-merge-nomask_to_ne4np4_nomask_aave_da_c130411.nc - - -lnd/clm2/mappingdata/maps/ne16np4/map_0.125x0.125_nomask_to_ne16np4_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/ne16np4/map_0.5x0.5_nomask_to_ne16np4_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/ne16np4/map_0.25x0.25_nomask_to_ne16np4_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/ne16np4/map_10x10min_nomask_to_ne16np4_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/ne16np4/map_5x5min_nomask_to_ne16np4_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/ne16np4/map_3x3min_nomask_to_ne16np4_nomask_aave_da_c210506.nc -lnd/clm2/mappingdata/maps/ne16np4/map_0.9x1.25_nomask_to_ne16np4_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/ne16np4/map_1km-merge-10min_HYDRO1K-merge-nomask_to_ne16np4_nomask_aave_da_c130408.nc - - -lnd/clm2/mappingdata/maps/ne30np4/map_0.125x0.125_nomask_to_ne30np4_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/ne30np4/map_0.5x0.5_nomask_to_ne30np4_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/ne30np4/map_0.25x0.25_nomask_to_ne30np4_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/ne30np4/map_10x10min_nomask_to_ne30np4_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/ne30np4/map_5x5min_nomask_to_ne30np4_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/ne30np4/map_3x3min_nomask_to_ne30np4_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/ne30np4/map_0.9x1.25_nomask_to_ne30np4_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/ne30np4/map_1km-merge-10min_HYDRO1K-merge-nomask_to_ne30np4_nomask_aave_da_c130405.nc - - -lnd/clm2/mappingdata/maps/ne60np4/map_0.125x0.125_nomask_to_ne60np4_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/ne60np4/map_0.5x0.5_nomask_to_ne60np4_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/ne60np4/map_0.25x0.25_nomask_to_ne60np4_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/ne60np4/map_10x10min_nomask_to_ne60np4_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/ne60np4/map_5x5min_nomask_to_ne60np4_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/ne60np4/map_3x3min_nomask_to_ne60np4_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/ne60np4/map_0.9x1.25_nomask_to_ne60np4_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/ne60np4/map_1km-merge-10min_HYDRO1K-merge-nomask_to_ne60np4_nomask_aave_da_c130405.nc - -lnd/clm2/mappingdata/maps/ne120np4/map_0.125x0.125_nomask_to_ne120np4_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/ne120np4/map_0.5x0.5_nomask_to_ne120np4_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/ne120np4/map_0.25x0.25_nomask_to_ne120np4_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/ne120np4/map_10x10min_nomask_to_ne120np4_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/ne120np4/map_5x5min_nomask_to_ne120np4_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/ne120np4/map_3x3min_nomask_to_ne120np4_nomask_aave_da_c210506.nc -lnd/clm2/mappingdata/maps/ne120np4/map_0.9x1.25_nomask_to_ne120np4_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/ne120np4/map_1km-merge-10min_HYDRO1K-merge-nomask_to_ne120np4_nomask_aave_da_c130405.nc - - - - - - - - - - -lnd/clm2/mappingdata/maps/0.125x0.125/map_0.125x0.125_nomask_to_0.125nldas2_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/0.125x0.125/map_0.5x0.5_nomask_to_0.125nldas2_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/0.125x0.125/map_0.25x0.25_nomask_to_0.125nldas2_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/0.125x0.125/map_3x3min_nomask_to_0.125nldas2_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/0.125x0.125/map_1km-merge-10min_HYDRO1K-merge-nomask_to_0.125nldas2_nomask_aave_da_c140702.nc -lnd/clm2/mappingdata/maps/0.125x0.125/map_5x5min_nomask_to_0.125nldas2_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/0.125x0.125/map_10x10min_nomask_to_0.125nldas2_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/0.125x0.125/map_0.9x1.25_nomask_to_0.125nldas2_nomask_aave_da_c200206.nc - - - -lnd/clm2/mappingdata/maps/5x5_amazon/map_0.125x0.125_nomask_to_5x5_amazon_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/5x5_amazon/map_0.5x0.5_nomask_to_5x5_amazon_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/5x5_amazon/map_0.25x0.25_nomask_to_5x5_amazon_nomask_aave_da_c200309.nc - - - -lnd/clm2/mappingdata/maps/ne0np4CONUS.ne30x8/map_5x5min_nomask_to_ne0np4CONUS.ne30x8_nomask_aave_da_c200426.nc -lnd/clm2/mappingdata/maps/ne0np4CONUS.ne30x8/map_10x10min_nomask_to_ne0np4CONUS.ne30x8_nomask_aave_da_c200426.nc -lnd/clm2/mappingdata/maps/ne0np4CONUS.ne30x8/map_1km-merge-10min_HYDRO1K-merge-nomask_to_ne0np4CONUS.ne30x8_nomask_aave_da_c200426.nc - - -lnd/clm2/mappingdata/maps/5x5_amazon/map_10x10min_nomask_to_5x5_amazon_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/5x5_amazon/map_5x5min_nomask_to_5x5_amazon_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/5x5_amazon/map_3x3min_nomask_to_5x5_amazon_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/5x5_amazon/map_0.9x1.25_nomask_to_5x5_amazon_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/5x5_amazon/map_1km-merge-10min_HYDRO1K-merge-nomask_to_5x5_amazon_nomask_aave_da_c130403.nc - -lnd/clm2/mappingdata/maps/ne240np4/map_0.125x0.125_nomask_to_ne240np4_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/ne240np4/map_10x10min_nomask_to_ne240np4_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/ne240np4/map_0.5x0.5_nomask_to_ne240np4_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/ne240np4/map_0.25x0.25_nomask_to_ne240np4_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/ne240np4/map_3x3min_nomask_to_ne240np4_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/ne240np4/map_5x5min_nomask_to_ne240np4_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/ne240np4/map_0.9x1.25_nomask_to_ne240np4_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/ne240np4/map_1km-merge-10min_HYDRO1K-merge-nomask_to_ne240np4_nomask_aave_da_c130405.nc - - - - -lnd/clm2/mappingdata/maps/0.125x0.125/map_0.125x0.125_nomask_to_0.125x0.125_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/0.125x0.125/map_10x10min_nomask_to_0.125x0.125_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/0.125x0.125/map_1km-merge-10min_HYDRO1K-merge-nomask_to_0.125x0.125_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/0.125x0.125/map_0.5x0.5_nomask_to_0.125x0.125_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/0.125x0.125/map_0.25x0.25_nomask_to_0.125x0.125_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/0.125x0.125/map_3x3min_nomask_to_0.125x0.125_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/0.125x0.125/map_5x5min_nomask_to_0.125x0.125_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/0.125x0.125/map_0.9x1.25_nomask_to_0.125x0.125_nomask_aave_da_c200206.nc - - - - - -lnd/clm2/mappingdata/maps/1km/map_0.5x0.5_nomask_to_1km-merge-10min_HYDRO1K-merge-nomask_aave_da_c200206.nc - - - - - - - -lnd/clm2/mappingdata/maps/94x192/map_0.5x0.5_nomask_to_94x192_nomask_aave_da_c110823.nc -lnd/clm2/mappingdata/maps/94x192/map_94x192_nomask_to_0.5x0.5_nomask_aave_da_c110823.nc -lnd/clm2/mappingdata/maps/94x192/map_1km-merge-10min_HYDRO1K-merge-nomask_to_94x192_nomask_aave_da_c190521.nc -lnd/clm2/mappingdata/maps/94x192/map_5x5min_nomask_to_94x192_nomask_aave_da_c110823.nc -lnd/clm2/mappingdata/maps/94x192/map_10x10min_nomask_to_94x192_nomask_aave_da_c110823.nc - - - - - - -lnd/clm2/mappingdata/maps/ARCTIC/map_1km-merge-10min_HYDRO1K-merge-nomask_to_ne0np4.ARCTIC.ne30x4_nomask_aave_da_c200426.nc -lnd/clm2/mappingdata/maps/ARCTIC/map_5x5min_nomask_to_ne0np4.ARCTIC.ne30x4_nomask_aave_da_c200426.nc -lnd/clm2/mappingdata/maps/ARCTIC/map_10x10min_nomask_to_ne0np4.ARCTIC.ne30x4_nomask_aave_da_c200426.nc - - - - - - -lnd/clm2/mappingdata/maps/ARCTICGRIS/map_1km-merge-10min_HYDRO1K-merge-nomask_to_ne0np4.ARCTICGRIS.ne30x8_nomask_aave_da_c200426.nc -lnd/clm2/mappingdata/maps/ARCTICGRIS/map_5x5min_nomask_to_ne0np4.ARCTICGRIS.ne30x8_nomask_aave_da_c200426.nc -lnd/clm2/mappingdata/maps/ARCTICGRIS/map_10x10min_nomask_to_ne0np4.ARCTICGRIS.ne30x8_nomask_aave_da_c200426.nc - - - - - - -lnd/clm2/mappingdata/maps/ne30np4.pg2/map_5x5min_nomask_to_ne30np4.pg2_nomask_aave_da_c200426.nc -lnd/clm2/mappingdata/maps/ne30np4.pg2/map_1km-merge-10min_HYDRO1K-merge-nomask_to_ne30np4.pg2_nomask_aave_da_c200426.nc -lnd/clm2/mappingdata/maps/ne30np4.pg2/map_10x10min_nomask_to_ne30np4.pg2_nomask_aave_da_c200426.nc - - - - - - -lnd/clm2/mappingdata/maps/ne30pg3/map_5x5min_nomask_to_ne30np4.pg3_nomask_aave_da_c200426.nc -lnd/clm2/mappingdata/maps/ne30pg3/map_10x10min_nomask_to_ne30np4.pg3_nomask_aave_da_c200426.nc -lnd/clm2/mappingdata/maps/ne30pg3/map_1km-merge-10min_HYDRO1K-merge-nomask_to_ne30np4.pg3_nomask_aave_da_c200426.nc - - - - - - -lnd/clm2/mappingdata/maps/ne120np4.pg2/map_10x10min_nomask_to_ne120np4.pg2_nomask_aave_da_c200426.nc -lnd/clm2/mappingdata/maps/ne120np4.pg2/map_5x5min_nomask_to_ne120np4.pg2_nomask_aave_da_c200426.nc -lnd/clm2/mappingdata/maps/ne120np4.pg2/map_1km-merge-10min_HYDRO1K-merge-nomask_to_ne120np4.pg2_nomask_aave_da_c200426.nc - - - - - - -lnd/clm2/mappingdata/maps/ne120np4.pg3/map_10x10min_nomask_to_ne120np4.pg3_nomask_aave_da_c200426.nc -lnd/clm2/mappingdata/maps/ne120np4.pg3/map_1km-merge-10min_HYDRO1K-merge-nomask_to_ne120np4.pg3_nomask_aave_da_c200426.nc -lnd/clm2/mappingdata/maps/ne120np4.pg3/map_5x5min_nomask_to_ne120np4.pg3_nomask_aave_da_c200426.nc - - @@ -2756,8 +1968,7 @@ use_crop=".true.">lnd/clm2/surfdata_map/ctsm5.1.dev052/landuse.timeseries_mpasa1 -TWS_inversion -TWS_inversion +TWS_inversion ZWT_inversion .true. .true. @@ -2901,6 +2112,7 @@ use_crop=".true.">lnd/clm2/surfdata_map/ctsm5.1.dev052/landuse.timeseries_mpasa1 off low +low .false. 0.26d00 diff --git a/bld/namelist_files/namelist_defaults_ctsm_tools.xml b/bld/namelist_files/namelist_defaults_ctsm_tools.xml deleted file mode 100644 index ff309c6fc9..0000000000 --- a/bld/namelist_files/namelist_defaults_ctsm_tools.xml +++ /dev/null @@ -1,7427 +0,0 @@ - - - - - - - - - - - - -none -SCRIP - - -lnd/clm2/mappingdata/grids/SCRIPgrid_0.23x0.31_nomask_c110308.nc -lnd/clm2/mappingdata/grids/SCRIPgrid_0.47x0.63_nomask_c170914.nc -lnd/clm2/mappingdata/grids/0.9x1.25_c110307.nc -lnd/clm2/mappingdata/grids/1.9x2.5_c110308.nc -lnd/clm2/mappingdata/grids/SCRIPgrid_2.5x3.33_nomask_c110308.nc -lnd/clm2/mappingdata/grids/SCRIPgrid_4x5_nomask_c110308.nc -lnd/clm2/mappingdata/grids/SCRIPgrid_10x15_nomask_c110308.nc - - -lnd/clm2/mappingdata/grids/SCRIPgrid_512x1024_nomask_c110308.nc -lnd/clm2/mappingdata/grids/SCRIPgrid_128x256_nomask_c110308.nc -lnd/clm2/mappingdata/grids/SCRIPgrid_94x192_nomask_c110308.nc -lnd/clm2/mappingdata/grids/SCRIPgrid_64x128_nomask_c110308.nc -lnd/clm2/mappingdata/grids/SCRIPgrid_48x96_nomask_c110308.nc -lnd/clm2/mappingdata/grids/SCRIPgrid_32x64_nomask_c110308.nc -lnd/clm2/mappingdata/grids/SCRIPgrid_8x16_nomask_c110308.nc - - -atm/cam/coords/C384_SCRIP_desc.181018.nc -atm/cam/coords/C192_SCRIP_desc.181018.nc -atm/cam/coords/C96_SCRIP_desc.181018.nc -atm/cam/coords/C48_SCRIP_desc.181018.nc -atm/cam/coords/C24_SCRIP_desc.181018.nc - - -lnd/clm2/mappingdata/grids/SCRIPgrid_ne240np4_nomask_c091227.nc -lnd/clm2/mappingdata/grids/SCRIPgrid_ne120np4_nomask_c101123.nc -lnd/clm2/mappingdata/grids/SCRIPgrid_ne60np4_nomask_c100408.nc -lnd/clm2/mappingdata/grids/SCRIPgrid_ne30np4_nomask_c101123.nc -lnd/clm2/mappingdata/grids/SCRIPgrid_ne16np4_nomask_c110512.nc - -atm/cam/coords/ne30pg2_scrip_c170608.nc -atm/cam/coords/ne30pg3_scrip_170604.nc -atm/cam/coords/ne120pg2_scrip_c170629.nc -atm/cam/coords/ne120pg3_scrip_c170628.nc - - -atm/cam/coords/ne0CONUSne30x8_scrip_c200107.nc -atm/cam/coords/ne0ARCTICGRISne30x8_scrip_c191209.nc -atm/cam/coords/ne0ARCTICne30x4_scrip_c191212.nc - - -lnd/clm2/mappingdata/grids/SCRIPgrid_0.125x0.125_nomask_c140702.nc -lnd/clm2/mappingdata/grids/SCRIPgrid_0.33x0.33_navy_c111207.nc - -lnd/clm2/mappingdata/grids/SCRIPgrid_360x720_nomask_c120830.nc - -lnd/clm2/mappingdata/grids/SCRIPgrid_0.5x0.5_nomask_c110308.nc -lnd/clm2/mappingdata/grids/SCRIPgrid_0.25x0.25_nomask_c200309.nc -lnd/clm2/mappingdata/grids/SCRIPgrid_5x5min_nomask_c200309.nc -lnd/clm2/mappingdata/grids/SCRIPgrid_10x10min_nomask_c110228.nc -lnd/clm2/mappingdata/grids/SCRIPgrid_3x3min_nomask_c200309.nc -64bit_offset - - - - -lnd/clm2/mappingdata/grids/UGRID_1km-merge-10min_HYDRO1K-merge-nomask_c130402.nc -netcdf4 -UGRID -landmesh - - -lnd/clm2/mappingdata/grids/SCRIPgrid_0.125nldas2_nomask_c190328.nc -lnd/clm2/mappingdata/grids/SCRIPgrid_1x1pt_brazil_nomask_c20211211.nc -lnd/clm2/mappingdata/grids/SCRIPgrid_1x1pt_mexicocityMEX_nomask_c110308.nc -lnd/clm2/mappingdata/grids/SCRIPgrid_1x1pt_numaIA_nomask_c110308.nc -lnd/clm2/mappingdata/grids/SCRIPgrid_1x1pt_smallvilleIA_nomask_c110308.nc -lnd/clm2/mappingdata/grids/SCRIPgrid_1x1pt_urbanc_alpha_nomask_c110308.nc -lnd/clm2/mappingdata/grids/SCRIPgrid_1x1pt_vancouverCAN_nomask_c110308.nc -lnd/clm2/mappingdata/grids/SCRIPgrid_5x5pt_amazon_nomask_c110308.nc - - -lnd/clm2/mappingdata/grids/SCRIPgrid_0.33x0.33_navy_c111207.nc -lnd/clm2/mappingdata/grids/SCRIPgrid_5x5_amazon_navy_c111207.nc -/glade/proj3/cseg/mapping/grids/gx1v6_090205.nc -/glade/proj3/cseg/mapping/grids/gx3v7_090903.nc -/glade/proj3/cseg/mapping/grids/tx1v1_090122.nc -/glade/proj3/cseg/mapping/grids/tx0.1v2_090127.nc - - - - - -nomask -nomask -nomask -nomask -nomask -nomask -nomask -nomask -nomask -nomask -nomask -nomask -nomask -nomask -nomask -nomask -nomask -nomask -nomask -nomask -nomask -nomask -nomask -HYDRO1K-merge-nomask -nomask - - -3x3min -0.5x0.5 -0.5x0.5 -0.25x0.25 -3x3min -0.25x0.25 -3x3min -0.25x0.25 -3x3min -0.25x0.25 -3x3min -5x5min -3x3min -10x10min -0.125x0.125 -5x5min -10x10min -5x5min -0.5x0.5 -0.5x0.5 -5x5min -0.5x0.5 -1km-merge-10min -0.9x1.25 - - -mksrf_flakwat -mksrf_fwetlnd -mksrf_fvocef -mksrf_flai -mksrf_fvegtyp -mksrf_fvegtyp -mksrf_furban -mksrf_fsoicol -mksrf_forganic -mksrf_fglacier -mksrf_fglacierregion -mksrf_fmax -mksrf_furbtopo -mksrf_fsoitex -mksrf_fgdp -mksrf_fpeat -mksrf_fsoildepth -mksrf_fabm -mksrf_ftopostats -mksrf_fvic - - -lnd/clm2/rawdata/mksrf_navyoro_20min.c010129.nc - - - -lnd/clm2/rawdata/pftcftdynharv.0.05x0.05.LUH2.histsimyr2005.c190116/mksrf_lai_histclm52deg005_earthstatmirca_2005.c190119.nc - - -lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_lai_78pfts_simyr2005.c170413.nc - - - -lnd/clm2/rawdata/mksrf_irrig_2160x4320_simyr2000.c110527.nc - -lnd/clm2/rawdata/mksrf_soitex.10level.c010119.nc - -lnd/clm2/rawdata/pftcftdynharv.0.05x0.05.LUH2.histsimyr2005.c190116/mksrf_soilcolor_histclm52deg005_earthstatmirca_2005.c190116.nc - - -lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_soilcolor_CMIP6_simyr2005.c170623.nc - -lnd/clm2/rawdata/mksrf_organic_10level_5x5min_ISRIC-WISE-NCSCD_nlev7_c120830.nc - -lnd/clm2/rawdata/mksrf_fmax_0.125x0.125_c200220.nc - - -lnd/clm2/rawdata/mksrf_LakePnDepth_3x3min_simyr2004_csplk_c151015.nc - -lnd/clm2/rawdata/mksrf_lanwat.050425.nc - - -lnd/clm2/rawdata/mksrf_vocef_0.5x0.5_simyr2000.c110531.nc - - -lnd/clm2/rawdata/mksrf_urban_0.05x0.05_simyr2000.c120621.nc - -lnd/clm2/rawdata/mksrf_urban_0.05x0.05_zerourbanpct.c181014.nc - - - -lnd/clm2/rawdata/mksrf_glacier_3x3min_simyr2000.c120926.nc -lnd/clm2/rawdata/mksrf_glacier_3x3min_simyr2000_mergeGreenland.c120921.nc - - -lnd/clm2/rawdata/mksrf_GlacierRegion_10x10min_nomask_c191120.nc - - -lnd/clm2/rawdata/mksrf_topo.10min.c191120.nc - - -lnd/clm2/rawdata/mksrf_gdp_0.5x0.5_AVHRR_simyr2000.c130228.nc -lnd/clm2/rawdata/mksrf_gdp_0.5x0_zerogdp.c200413.nc - -lnd/clm2/rawdata/mksrf_peatf_0.5x0.5_AVHRR_simyr2000.c130228.nc - -lnd/clm2/rawdata/mksf_soilthk_5x5min_ORNL-Soil_simyr1900-2015_c170630.nc - -lnd/clm2/rawdata/mksrf_abm_0.5x0.5_AVHRR_simyr2000.c130201.nc -lnd/clm2/rawdata/mksrf_abm_0.5x0.5_missingabm.c200413.nc - - -lnd/clm2/rawdata/mksrf_topostats_1km-merge-10min_HYDRO1K-merge-nomask_simyr2000.c130402.nc - -lnd/clm2/rawdata/mksrf_vic_0.9x1.25_GRDC_simyr2000.c130307.nc - - - - -lnd/clm2/rawdata/pftcftdynharv.0.05x0.05.LUH2.histsimyr2005.c190116/mksrf_landuse_clm52deg005_histLUH2_1850.c190119.nc - -lnd/clm2/rawdata/pftcftdynharv.0.05x0.05.LUH2.histsimyr2005.c190116/mksrf_landuse_clm52deg005_histLUH2_2005.c190119.nc - - - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_850.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_851.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_852.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_853.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_854.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_855.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_856.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_857.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_858.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_859.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_860.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_861.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_862.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_863.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_864.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_865.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_866.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_867.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_868.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_869.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_870.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_871.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_872.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_873.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_874.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_875.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_876.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_877.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_878.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_879.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_880.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_881.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_882.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_883.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_884.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_885.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_886.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_887.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_888.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_889.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_890.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_891.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_892.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_893.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_894.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_895.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_896.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_897.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_898.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_899.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_900.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_901.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_902.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_903.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_904.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_905.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_906.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_907.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_908.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_909.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_910.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_911.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_912.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_913.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_914.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_915.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_916.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_917.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_918.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_919.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_920.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_921.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_922.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_923.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_924.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_925.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_926.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_927.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_928.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_929.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_930.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_931.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_932.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_933.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_934.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_935.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_936.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_937.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_938.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_939.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_940.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_941.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_942.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_943.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_944.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_945.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_946.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_947.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_948.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_949.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_950.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_951.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_952.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_953.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_954.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_955.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_956.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_957.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_958.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_959.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_960.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_961.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_962.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_963.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_964.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_965.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_966.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_967.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_968.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_969.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_970.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_971.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_972.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_973.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_974.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_975.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_976.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_977.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_978.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_979.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_980.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_981.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_982.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_983.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_984.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_985.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_986.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_987.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_988.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_989.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_990.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_991.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_992.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_993.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_994.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_995.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_996.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_997.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_998.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_999.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1000.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1001.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1002.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1003.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1004.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1005.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1006.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1007.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1008.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1009.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1010.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1011.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1012.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1013.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1014.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1015.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1016.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1017.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1018.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1019.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1020.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1021.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1022.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1023.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1024.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1025.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1026.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1027.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1028.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1029.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1030.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1031.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1032.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1033.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1034.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1035.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1036.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1037.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1038.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1039.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1040.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1041.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1042.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1043.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1044.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1045.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1046.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1047.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1048.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1049.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1050.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1051.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1052.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1053.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1054.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1055.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1056.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1057.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1058.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1059.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1060.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1061.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1062.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1063.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1064.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1065.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1066.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1067.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1068.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1069.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1070.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1071.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1072.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1073.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1074.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1075.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1076.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1077.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1078.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1079.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1080.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1081.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1082.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1083.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1084.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1085.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1086.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1087.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1088.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1089.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1090.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1091.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1092.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1093.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1094.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1095.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1096.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1097.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1098.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1099.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1100.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1101.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1102.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1103.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1104.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1105.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1106.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1107.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1108.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1109.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1110.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1111.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1112.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1113.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1114.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1115.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1116.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1117.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1118.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1119.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1120.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1121.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1122.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1123.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1124.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1125.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1126.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1127.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1128.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1129.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1130.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1131.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1132.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1133.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1134.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1135.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1136.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1137.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1138.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1139.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1140.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1141.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1142.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1143.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1144.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1145.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1146.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1147.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1148.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1149.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1150.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1151.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1152.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1153.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1154.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1155.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1156.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1157.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1158.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1159.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1160.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1161.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1162.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1163.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1164.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1165.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1166.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1167.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1168.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1169.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1170.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1171.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1172.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1173.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1174.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1175.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1176.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1177.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1178.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1179.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1180.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1181.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1182.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1183.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1184.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1185.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1186.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1187.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1188.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1189.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1190.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1191.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1192.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1193.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1194.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1195.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1196.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1197.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1198.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1199.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1200.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1201.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1202.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1203.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1204.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1205.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1206.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1207.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1208.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1209.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1210.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1211.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1212.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1213.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1214.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1215.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1216.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1217.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1218.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1219.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1220.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1221.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1222.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1223.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1224.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1225.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1226.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1227.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1228.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1229.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1230.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1231.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1232.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1233.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1234.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1235.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1236.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1237.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1238.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1239.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1240.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1241.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1242.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1243.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1244.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1245.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1246.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1247.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1248.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1249.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1250.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1251.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1252.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1253.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1254.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1255.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1256.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1257.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1258.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1259.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1260.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1261.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1262.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1263.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1264.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1265.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1266.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1267.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1268.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1269.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1270.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1271.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1272.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1273.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1274.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1275.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1276.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1277.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1278.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1279.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1280.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1281.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1282.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1283.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1284.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1285.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1286.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1287.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1288.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1289.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1290.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1291.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1292.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1293.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1294.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1295.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1296.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1297.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1298.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1299.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1300.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1301.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1302.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1303.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1304.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1305.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1306.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1307.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1308.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1309.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1310.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1311.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1312.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1313.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1314.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1315.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1316.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1317.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1318.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1319.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1320.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1321.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1322.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1323.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1324.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1325.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1326.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1327.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1328.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1329.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1330.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1331.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1332.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1333.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1334.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1335.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1336.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1337.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1338.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1339.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1340.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1341.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1342.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1343.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1344.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1345.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1346.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1347.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1348.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1349.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1350.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1351.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1352.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1353.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1354.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1355.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1356.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1357.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1358.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1359.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1360.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1361.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1362.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1363.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1364.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1365.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1366.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1367.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1368.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1369.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1370.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1371.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1372.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1373.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1374.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1375.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1376.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1377.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1378.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1379.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1380.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1381.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1382.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1383.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1384.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1385.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1386.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1387.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1388.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1389.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1390.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1391.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1392.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1393.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1394.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1395.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1396.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1397.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1398.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1399.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1400.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1401.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1402.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1403.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1404.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1405.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1406.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1407.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1408.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1409.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1410.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1411.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1412.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1413.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1414.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1415.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1416.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1417.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1418.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1419.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1420.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1421.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1422.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1423.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1424.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1425.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1426.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1427.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1428.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1429.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1430.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1431.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1432.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1433.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1434.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1435.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1436.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1437.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1438.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1439.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1440.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1441.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1442.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1443.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1444.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1445.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1446.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1447.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1448.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1449.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1450.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1451.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1452.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1453.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1454.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1455.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1456.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1457.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1458.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1459.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1460.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1461.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1462.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1463.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1464.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1465.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1466.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1467.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1468.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1469.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1470.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1471.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1472.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1473.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1474.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1475.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1476.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1477.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1478.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1479.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1480.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1481.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1482.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1483.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1484.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1485.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1486.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1487.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1488.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1489.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1490.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1491.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1492.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1493.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1494.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1495.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1496.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1497.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1498.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1499.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1500.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1501.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1502.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1503.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1504.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1505.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1506.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1507.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1508.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1509.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1510.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1511.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1512.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1513.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1514.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1515.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1516.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1517.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1518.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1519.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1520.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1521.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1522.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1523.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1524.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1525.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1526.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1527.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1528.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1529.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1530.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1531.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1532.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1533.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1534.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1535.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1536.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1537.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1538.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1539.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1540.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1541.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1542.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1543.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1544.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1545.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1546.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1547.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1548.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1549.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1550.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1551.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1552.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1553.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1554.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1555.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1556.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1557.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1558.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1559.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1560.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1561.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1562.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1563.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1564.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1565.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1566.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1567.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1568.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1569.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1570.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1571.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1572.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1573.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1574.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1575.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1576.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1577.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1578.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1579.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1580.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1581.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1582.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1583.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1584.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1585.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1586.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1587.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1588.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1589.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1590.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1591.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1592.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1593.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1594.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1595.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1596.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1597.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1598.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1599.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1600.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1601.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1602.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1603.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1604.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1605.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1606.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1607.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1608.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1609.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1610.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1611.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1612.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1613.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1614.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1615.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1616.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1617.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1618.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1619.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1620.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1621.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1622.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1623.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1624.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1625.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1626.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1627.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1628.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1629.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1630.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1631.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1632.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1633.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1634.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1635.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1636.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1637.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1638.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1639.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1640.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1641.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1642.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1643.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1644.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1645.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1646.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1647.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1648.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1649.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1650.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1651.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1652.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1653.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1654.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1655.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1656.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1657.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1658.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1659.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1660.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1661.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1662.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1663.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1664.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1665.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1666.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1667.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1668.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1669.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1670.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1671.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1672.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1673.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1674.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1675.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1676.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1677.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1678.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1679.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1680.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1681.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1682.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1683.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1684.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1685.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1686.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1687.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1688.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1689.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1690.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1691.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1692.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1693.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1694.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1695.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1696.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1697.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1698.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1699.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1700.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1701.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1702.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1703.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1704.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1705.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1706.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1707.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1708.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1709.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1710.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1711.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1712.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1713.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1714.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1715.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1716.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1717.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1718.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1719.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1720.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1721.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1722.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1723.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1724.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1725.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1726.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1727.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1728.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1729.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1730.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1731.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1732.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1733.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1734.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1735.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1736.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1737.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1738.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1739.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1740.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1741.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1742.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1743.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1744.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1745.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1746.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1747.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1748.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1749.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1750.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1751.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1752.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1753.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1754.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1755.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1756.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1757.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1758.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1759.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1760.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1761.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1762.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1763.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1764.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1765.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1766.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1767.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1768.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1769.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1770.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1771.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1772.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1773.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1774.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1775.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1776.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1777.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1778.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1779.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1780.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1781.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1782.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1783.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1784.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1785.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1786.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1787.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1788.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1789.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1790.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1791.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1792.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1793.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1794.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1795.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1796.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1797.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1798.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1799.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1800.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1801.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1802.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1803.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1804.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1805.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1806.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1807.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1808.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1809.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1810.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1811.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1812.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1813.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1814.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1815.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1816.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1817.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1818.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1819.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1820.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1821.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1822.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1823.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1824.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1825.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1826.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1827.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1828.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1829.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1830.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1831.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1832.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1833.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1834.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1835.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1836.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1837.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1838.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1839.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1840.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1841.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1842.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1843.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1844.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1845.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1846.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1847.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1848.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1849.c171012.nc - - - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1850.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1851.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1852.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1853.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1854.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1855.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1856.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1857.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1858.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1859.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1860.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1861.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1862.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1863.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1864.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1865.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1866.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1867.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1868.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1869.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1870.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1871.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1872.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1873.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1874.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1875.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1876.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1877.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1878.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1879.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1880.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1881.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1882.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1883.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1884.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1885.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1886.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1887.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1888.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1889.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1890.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1891.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1892.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1893.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1894.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1895.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1896.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1897.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1898.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1899.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1900.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1901.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1902.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1903.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1904.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1905.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1906.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1907.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1908.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1909.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1910.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1911.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1912.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1913.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1914.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1915.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1916.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1917.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1918.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1919.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1920.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1921.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1922.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1923.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1924.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1925.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1926.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1927.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1928.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1929.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1930.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1931.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1932.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1933.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1934.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1935.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1936.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1937.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1938.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1939.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1940.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1941.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1942.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1943.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1944.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1945.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1946.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1947.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1948.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1949.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1950.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1951.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1952.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1953.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1954.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1955.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1956.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1957.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1958.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1959.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1960.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1961.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1962.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1963.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1964.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1965.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1966.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1967.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1968.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1969.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1970.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1971.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1972.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1973.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1974.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1975.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1976.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1977.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1978.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1979.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1980.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1981.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1982.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1983.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1984.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1985.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1986.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1987.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1988.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1989.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1990.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1991.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1992.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1993.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1994.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1995.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1996.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1997.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1998.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1999.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_2000.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_2001.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_2002.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_2003.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_2004.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_2005.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_2006.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_2007.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_2008.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_2009.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_2010.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_2011.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_2012.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_2013.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_2014.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_2015.c170629.nc - - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.simyrPtVg.c181106/mksrf_landuse_potvegclm50_LUH2.c181106.nc - - - - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2016.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2017.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2018.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2019.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2020.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2021.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2022.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2023.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2024.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2025.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2026.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2027.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2028.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2029.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2030.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2031.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2032.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2033.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2034.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2035.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2036.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2037.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2038.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2039.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2040.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2041.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2042.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2043.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2044.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2045.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2046.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2047.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2048.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2049.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2050.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2051.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2052.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2053.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2054.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2055.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2056.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2057.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2058.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2059.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2060.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2061.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2062.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2063.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2064.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2065.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2066.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2067.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2068.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2069.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2070.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2071.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2072.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2073.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2074.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2075.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2076.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2077.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2078.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2079.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2080.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2081.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2082.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2083.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2084.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2085.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2086.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2087.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2088.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2089.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2090.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2091.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2092.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2093.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2094.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2095.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2096.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2097.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2098.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2099.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2100.c181217.nc - - - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2016.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2017.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2018.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2019.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2020.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2021.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2022.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2023.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2024.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2025.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2026.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2027.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2028.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2029.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2030.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2031.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2032.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2033.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2034.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2035.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2036.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2037.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2038.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2039.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2040.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2041.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2042.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2043.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2044.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2045.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2046.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2047.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2048.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2049.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2050.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2051.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2052.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2053.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2054.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2055.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2056.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2057.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2058.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2059.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2060.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2061.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2062.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2063.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2064.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2065.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2066.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2067.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2068.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2069.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2070.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2071.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2072.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2073.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2074.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2075.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2076.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2077.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2078.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2079.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2080.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2081.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2082.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2083.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2084.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2085.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2086.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2087.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2088.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2089.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2090.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2091.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2092.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2093.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2094.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2095.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2096.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2097.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2098.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2099.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2100.c181217.nc - - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2016.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2017.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2018.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2019.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2020.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2021.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2022.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2023.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2024.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2025.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2026.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2027.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2028.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2029.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2030.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2031.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2032.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2033.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2034.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2035.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2036.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2037.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2038.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2039.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2040.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2041.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2042.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2043.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2044.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2045.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2046.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2047.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2048.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2049.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2050.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2051.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2052.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2053.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2054.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2055.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2056.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2057.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2058.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2059.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2060.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2061.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2062.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2063.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2064.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2065.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2066.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2067.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2068.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2069.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2070.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2071.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2072.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2073.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2074.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2075.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2076.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2077.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2078.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2079.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2080.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2081.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2082.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2083.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2084.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2085.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2086.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2087.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2088.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2089.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2090.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2091.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2092.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2093.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2094.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2095.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2096.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2097.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2098.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2099.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2100.c181217.nc - - - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2016.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2017.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2018.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2019.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2020.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2021.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2022.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2023.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2024.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2025.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2026.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2027.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2028.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2029.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2030.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2031.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2032.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2033.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2034.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2035.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2036.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2037.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2038.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2039.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2040.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2041.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2042.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2043.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2044.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2045.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2046.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2047.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2048.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2049.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2050.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2051.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2052.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2053.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2054.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2055.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2056.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2057.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2058.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2059.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2060.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2061.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2062.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2063.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2064.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2065.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2066.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2067.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2068.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2069.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2070.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2071.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2072.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2073.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2074.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2075.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2076.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2077.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2078.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2079.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2080.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2081.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2082.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2083.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2084.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2085.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2086.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2087.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2088.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2089.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2090.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2091.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2092.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2093.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2094.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2095.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2096.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2097.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2098.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2099.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2100.c181217.nc - - - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2016.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2017.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2018.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2019.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2020.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2021.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2022.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2023.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2024.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2025.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2026.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2027.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2028.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2029.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2030.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2031.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2032.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2033.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2034.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2035.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2036.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2037.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2038.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2039.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2040.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2041.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2042.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2043.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2044.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2045.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2046.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2047.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2048.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2049.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2050.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2051.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2052.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2053.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2054.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2055.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2056.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2057.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2058.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2059.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2060.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2061.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2062.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2063.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2064.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2065.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2066.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2067.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2068.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2069.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2070.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2071.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2072.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2073.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2074.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2075.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2076.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2077.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2078.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2079.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2080.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2081.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2082.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2083.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2084.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2085.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2086.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2087.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2088.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2089.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2090.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2091.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2092.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2093.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2094.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2095.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2096.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2097.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2098.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2099.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2100.c181217.nc - - - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2016.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2017.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2018.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2019.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2020.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2021.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2022.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2023.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2024.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2025.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2026.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2027.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2028.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2029.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2030.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2031.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2032.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2033.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2034.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2035.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2036.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2037.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2038.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2039.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2040.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2041.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2042.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2043.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2044.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2045.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2046.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2047.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2048.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2049.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2050.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2051.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2052.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2053.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2054.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2055.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2056.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2057.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2058.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2059.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2060.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2061.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2062.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2063.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2064.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2065.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2066.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2067.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2068.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2069.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2070.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2071.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2072.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2073.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2074.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2075.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2076.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2077.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2078.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2079.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2080.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2081.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2082.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2083.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2084.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2085.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2086.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2087.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2088.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2089.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2090.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2091.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2092.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2093.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2094.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2095.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2096.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2097.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2098.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2099.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2100.c181217.nc - - - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2016.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2017.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2018.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2019.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2020.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2021.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2022.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2023.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2024.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2025.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2026.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2027.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2028.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2029.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2030.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2031.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2032.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2033.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2034.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2035.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2036.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2037.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2038.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2039.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2040.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2041.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2042.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2043.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2044.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2045.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2046.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2047.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2048.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2049.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2050.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2051.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2052.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2053.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2054.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2055.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2056.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2057.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2058.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2059.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2060.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2061.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2062.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2063.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2064.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2065.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2066.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2067.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2068.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2069.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2070.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2071.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2072.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2073.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2074.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2075.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2076.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2077.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2078.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2079.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2080.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2081.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2082.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2083.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2084.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2085.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2086.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2087.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2088.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2089.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2090.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2091.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2092.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2093.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2094.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2095.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2096.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2097.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2098.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2099.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2100.c181217.nc - - - - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2016.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2017.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2018.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2019.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2020.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2021.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2022.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2023.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2024.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2025.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2026.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2027.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2028.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2029.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2030.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2031.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2032.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2033.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2034.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2035.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2036.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2037.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2038.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2039.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2040.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2041.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2042.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2043.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2044.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2045.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2046.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2047.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2048.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2049.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2050.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2051.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2052.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2053.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2054.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2055.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2056.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2057.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2058.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2059.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2060.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2061.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2062.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2063.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2064.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2065.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2066.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2067.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2068.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2069.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2070.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2071.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2072.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2073.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2074.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2075.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2076.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2077.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2078.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2079.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2080.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2081.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2082.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2083.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2084.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2085.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2086.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2087.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2088.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2089.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2090.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2091.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2092.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2093.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2094.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2095.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2096.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2097.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2098.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2099.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2100.c171005.nc - - - - -atm/waccm/lb/LBC_17500116-20150116_CMIP6_0p5degLat_c180905.nc -atm/waccm/lb/LBC_1750-2015_CMIP6_GlobAnnAvg_c180926.nc - -atm/waccm/lb/LBC_20140116-25001216_CMIP6_SSP119_0p5degLat_c190514.nc -atm/waccm/lb/LBC_20140116-25001216_CMIP6_SSP126_0p5degLat_c180905.nc -atm/waccm/lb/LBC_20140116-25001216_CMIP6_SSP245_0p5degLat_c180905.nc -atm/waccm/lb/LBC_20140116-25001216_CMIP6_SSP370_0p5degLat_c180905.nc -atm/waccm/lb/LBC_20140116-25001216_CMIP6_SSP119_0p5degLat_c190514.nc -atm/waccm/lb/LBC_20140116-25001216_CMIP6_SSP460_0p5degLat_c180905.nc -atm/waccm/lb/LBC_20140116-25001216_CMIP6_SSP534os_0p5degLat_c180905.nc -atm/waccm/lb/LBC_20140116-25001216_CMIP6_SSP585_0p5degLat_c180905.nc - -atm/waccm/lb/LBC_2014-2500_CMIP6_SSP119_0p5degLat_GlobAnnAvg_c190514.nc -atm/waccm/lb/LBC_2014-2500_CMIP6_SSP126_0p5degLat_GlobAnnAvg_c190301.nc -atm/waccm/lb/LBC_2014-2500_CMIP6_SSP245_0p5degLat_GlobAnnAvg_c190301.nc -atm/waccm/lb/LBC_2014-2500_CMIP6_SSP370_0p5degLat_GlobAnnAvg_c190301.nc -atm/waccm/lb/LBC_2014-2500_CMIP6_SSP434_0p5degLat_GlobAnnAvg_c190514.nc -atm/waccm/lb/LBC_2014-2500_CMIP6_SSP460_0p5degLat_GlobAnnAvg_c190301.nc -atm/waccm/lb/LBC_2014-2500_CMIP6_SSP534os_0p5degLat_GlobAnnAvg_c190301.nc -atm/waccm/lb/LBC_2014-2500_CMIP6_SSP585_0p5degLat_GlobAnnAvg_c190301.nc - - diff --git a/bld/namelist_files/namelist_defaults_drydep.xml b/bld/namelist_files/namelist_defaults_drydep.xml index 9933d5cee3..08bb5adaef 100644 --- a/bld/namelist_files/namelist_defaults_drydep.xml +++ b/bld/namelist_files/namelist_defaults_drydep.xml @@ -25,6 +25,7 @@ attributes from the config_cache.xml file (with keys converted to upper-case). 'ISOP = isoprene', 'C10H16 = pinene_a + carene_3 + thujene_a', 'CH3OH = methanol', 'C2H5OH = ethanol', 'CH2O = formaldehyde', 'CH3CHO = acetaldehyde', 'CH3COOH = acetic_acid', 'CH3COCH3 = acetone' +atm/cam/chem/trop_mozart/emis/megan21_emis_factors_78pft_c20161108.nc atm/cam/chem/trop_mozart/emis/megan21_emis_factors_78pft_c20161108.nc atm/cam/chem/trop_mozart/emis/megan21_emis_factors_78pft_c20161108.nc atm/cam/chem/trop_mozart/emis/megan21_emis_factors_78pft_c20161108.nc diff --git a/bld/namelist_files/namelist_defaults_overall.xml b/bld/namelist_files/namelist_defaults_overall.xml index df9981efdf..479b2a02b7 100644 --- a/bld/namelist_files/namelist_defaults_overall.xml +++ b/bld/namelist_files/namelist_defaults_overall.xml @@ -22,29 +22,22 @@ determine default values for namelists. --> +arb_ic +cold +cold +cold +startup +startup + + cold cold cold cold cold cold -arb_ic -arb_ic -arb_ic -arb_ic -arb_ic -arb_ic -startup -startup -startup -startup -startup -startup -arb_ic -arb_ic -arb_ic -arb_ic -cold +cold +cold arb_ic diff --git a/bld/namelist_files/namelist_definition.xsl b/bld/namelist_files/namelist_definition.xsl index 545d810e52..7917cc262f 100644 --- a/bld/namelist_files/namelist_definition.xsl +++ b/bld/namelist_files/namelist_definition.xsl @@ -252,18 +252,6 @@

These are namelist items that appear in the CLM Tools under components/clm/tools.

- - - - - - - - - - -
CLM mksurfdata
NameTypeDescription
Valid values
- @@ -276,17 +264,6 @@
CLM mkgriddata
Name
- - - - - - - - - - -
CLM mkmapdata
NameTypeDescription
Valid values
diff --git a/bld/namelist_files/namelist_definition_ctsm.xml b/bld/namelist_files/namelist_definition_ctsm.xml index a2e9fb86da..99b3163450 100644 --- a/bld/namelist_files/namelist_definition_ctsm.xml +++ b/bld/namelist_files/namelist_definition_ctsm.xml @@ -171,7 +171,7 @@ dust optics type for SNICAR snow albedo calculation snow grain shape used in SNICAR snow albedo calculation -(snicar_dust_optics='hexagonal_plate' is supported in ctsm5.1 and 'sphere' in older model versions; others are EXPERIMENTAL, UNSUPPORTED, and UNTESTED!) +(snicar_snw_shape='hexagonal_plate' is supported in ctsm5.1 and 'sphere' in older model versions; others are EXPERIMENTAL, UNSUPPORTED, and UNTESTED!) + +If true, any ocean (i.e., wetland) points on the surface dataset are +converted to bare ground (or whatever vegetation is given in that grid +cell - but typically this will be bare ground due to lack of vegetation +in grid cells with 100% ocean). + + @@ -1366,238 +1374,6 @@ Toggle to turn on the dynamic root model Toggle to turn on on diagnostic Snow Radiative Effect - - - - - -SCRIP format grid data file - - - -Flag to pass to the ESMF mapping utility, telling it what kind of large -file support is needed for an output file generated with this grid as -either the source or destination ('none', '64bit_offset' or 'netcdf4'). - - - -Flag to pass to the ESMF mapping utility, telling it what kind of grid -file this is (SCRIP or UGRID). - - - -For UGRID files, flag to pass to the ESMF mapping utility, telling it the -name of the dummy variable that has all of the topology information stored -in its attributes. (Only used if scripgriddata_src_type = UGRID.) - - - - - - -Output of "git describe" to give the tag/commit the version being used corresponds to - - - -Filename for mksurfdata_map to remap raw data into the output surface dataset - - - -Plant Function Type dataset for mksurfdata - - - -Harvest dataset for mksurfdata - - - -Dataset for percent glacier land-unit for mksurfdata - - - -Dataset for glacier region ID for mksurfdata - - - -Dataset for topography used to define urban threshold - - - -Leaf Area Index dataset for mksurfdata - - - -Soil texture dataset for mksurfdata - - - -Soil color dataset for mksurfdata - - - -Soil max fraction dataset for mksurfdata - - - -High resolution land mask/fraction dataset for mksurfdata -(used for glacier_mec land-units) - - - -Type of grid to create for mksurfdata - - - -Grid file at the output resolution for mksurfdata - - - -Text file with filepaths (or list of XML elements) for vegetation fractions -and harvesting for each year to run over for mksurfdata to be able to model -transient land-use change - - - -High resolution topography dataset for mksurfdata -(used for glacier_mec land-units) - - - -Irrigation dataset for mksurfdata - - - -Organic soil dataset for mksurfdata - - - -Lake water dataset for mksurfdata - - - -Wetland dataset for mksurfdata - - - -Urban dataset for mksurfdata - - - -Biogenic Volatile Organic Compounds (VOC) emissions dataset for mksurfdata - - - -GDP dataset for mksurfdata - - - -Peat dataset for mksurfdata - - - -Soil depth dataset for mksurfdata - - - -Agricultural burning dominant month dataset for mksurfdata - - - -Topography statistics dataset for mksurfdata - - - -VIC parameters dataset for mksurfdata - - - -If TRUE, output variables in double precision for mksurfdata - - - -If TRUE, ignore other files, and set the output percentage to 100% urban and -zero for other land-use types. - - - -If TRUE, set wetland to 0% over land (renormalizing other landcover types as needed); -wetland will only be used for ocean points. - - - -Number of Plant Functional Types (excluding bare-soil) - - - -Plant Function Type index to override global file with for mksurfdata - - - -Plant Function Type fraction to override global file with for mksurfdata - - - -Soil color index to override global file with for mksurfdata - - - -Soil maximum fraction to override global file with for mksurfdata - - - -Soil percent sand to override global file with for mksurfdata - - - -Soil percent clay to override global file with for mksurfdata - - - @@ -1943,7 +1719,6 @@ prescribed data. Toggle to turn on use of LAI streams in place of the LAI on the surface dataset when using Satellite Phenology mode. -(EXPERIMENTAL, UNSUPPORTED, and UNTESTED!) - -Horizontal grid resolutions for mksurfdata input files - - - @@ -2245,13 +2013,6 @@ CLM run type. 'branch' is a restart run in which properties of the output history files may be changed. - -Horizontal resolutions -Note: 0.25x0.25, 0.5x0.5, 5x5min, 10x10min, 3x3min, 1km-merge-10min and 0.33x0.33 are only used for CLM toolsI - - @@ -2268,13 +2029,15 @@ hist means do NOT use a future scenario, just use historical data. Land mask description + + valid_values="clm4_5_CRUv7,clm4_5_GSWP3v1,clm4_5_cam6.0,clm4_5_cam5.0,clm4_5_cam4.0,clm5_0_cam6.0,clm5_0_cam5.0,clm5_0_cam4.0,clm5_0_CRUv7,clm5_0_GSWP3v1,clm5_1_GSWP3v1,clm5_1_CRUv7,clm5_1_cam6.0,clm5_1_cam5.0,clm5_1_cam4.0,clm6_0_GSWP3v1,clm6_0_cam6.0,clm6_0_cam5.0,clm6_0_cam4.0"> General configuration of model version and atmospheric forcing to tune the model to run under. This sets the model to run with constants and initial conditions that were set to run well under the configuration of model version and atmospheric forcing. To run well constants would need to be changed to run with a different type of atmospheric forcing. +(Some options for the newest physics will be based on previous tuning, and buildnml will let you know about this) $namelist, - var => undef, - hgrid => undef, - config => undef, - cesm => undef, - csmdata => undef, - demand => undef, - test => undef, - onlyfiles => undef, - fileonly => undef, - silent => undef, - usrname => undef, - help => undef, - options => undef, - ); - - my $cmdline = "@ARGV"; - GetOptions( - "f|file=s" => \$opts{'file'}, - "n|namelist=s" => \$opts{'namelist'}, - "v|var=s" => \$opts{'var'}, - "r|res=s" => \$opts{'hgrid'}, - "config=s" => \$opts{'config'}, - "cesm" => \$opts{'cesm'}, - "csmdata=s" => \$opts{'csmdata'}, - "demand" => \$opts{'demand'}, - "options=s" => \$opts{'options'}, - "t|test" => \$opts{'test'}, - "onlyfiles" => \$opts{'onlyfiles'}, - "filenameonly" => \$opts{'fileonly'}, - "justvalues" => \$opts{'justvalues'}, - "usrname=s" => \$opts{'usrname'}, - "s|silent" => \$opts{'silent'}, - "h|elp" => \$opts{'help'}, - ) or usage(); - - # Check for unparsed arguments - if (@ARGV) { - print "ERROR: unrecognized arguments: @ARGV\n"; - usage(); - } - if ( $opts{'help'} ) { - usage(); - } - # Set if should do extra printing or not (if silent mode is not set) - my $printing = 1; - if ( defined($opts{'silent'}) ) { - $printing = 0; - } - # Get list of options from command-line into the settings hash - my %settings; - if ( defined($opts{'options'}) ) { - $opts{'options'} =~ s/\s//g; # Remove all white-space in options - my @optionlist = split( ",", $opts{'options'} ); - foreach my $item ( @optionlist ) { - my ($key,$value) = split( "=", $item ); - $settings{$key} = $value; - } - } - my $csmdata = ""; - if ( defined($opts{'fileonly'}) ) { - if ( ! defined($opts{'justvalues'}) ) { print "When -filenameonly option used, -justvalues is set as well\n" if $printing; } - if ( ! defined($opts{'onlyfiles'}) ) { print "When -filenameonly option used, -onlyfiles is set as well\n" if $printing; } - $opts{'justvalues'} = 1; - $opts{'onlyfiles'} = 1; - } - # List of input options - my %inputopts; - # This namelist files under the cime directories are in version 2 format and can't be read by perl code EBK 11/15/2016 - my @nl_definition_files = ("$cfgdir/namelist_files/namelist_definition_drv.xml", - "$cfgdir/namelist_files/namelist_definition_ctsm.xml" - ); - $inputopts{empty_cfg_file} = "$cfgdir/config_files/config_definition_ctsm.xml"; - $inputopts{nldef_files} = \@nl_definition_files; - $inputopts{namelist} = $opts{namelist}; - $inputopts{printing} = $printing; - $inputopts{cfgdir} = $cfgdir; - $inputopts{ProgName} = $ProgName; - $inputopts{cmdline} = $cmdline; - - my $exitearly = 0; - my $definition = Build::NamelistDefinition->new( $nl_definition_files[0] ); - foreach my $nl_defin_file ( @nl_definition_files ) { - if ( ! -f "$nl_defin_file" ) { - die "($ProgName $cmdline) ERROR:: bad namelist definition filename: $nl_defin_file.\n"; - } - $definition->add( "$nl_defin_file" ); - } - - if ( ! defined($opts{csmdata}) ) { - $inputopts{csmdata} = "default"; - } else { - $inputopts{csmdata} = $opts{csmdata}; - } - if ( defined($opts{cesm}) ) { - $inputopts{csmdata} = '$DIN_LOC_ROOT'; - } - if ( ! defined($opts{config}) ) { - $inputopts{config} = "noconfig"; - } else { - $inputopts{config} = $opts{config}; - } - if ( ! defined($opts{var}) ) { - $settings{'var'} = undef; - } elsif ( $opts{var} eq "list" ) { - print "Valid variables: " if $printing; - my @vars = $definition->get_var_names( ); - print "@vars\n"; - $exitearly = 1; - } else { - $settings{'var'} = $opts{'var'}; - } - if ( ! defined($opts{hgrid}) ) { - $inputopts{hgrid} = "any"; - } elsif ( $opts{hgrid} eq "list" ) { - print "Valid resolutions: " if $printing; - my @hgrids = $definition->get_valid_values( "res", 'noquotes'=>1 ); - print "@hgrids\n"; - $exitearly = 1; - } else { - if ( ! $definition->is_valid_value( "res", $opts{hgrid}, 'noquotes'=>1 ) ) { - if ( $opts{'hgrid'} ne $opts{'usrname'} ) { - die "($ProgName $cmdline) ERROR:: invalid resolution entered.\n"; - } - } - $inputopts{hgrid} = $opts{hgrid}; - } - # The namelist defaults file contains default values for all required namelist variables. - my @nl_defaults_files = ( "$cfgdir/namelist_files/namelist_defaults_overall.xml" ); - if ( defined($opts{'usrname'}) ) { - my $nl_defaults_file = "$cfgdir/namelist_files/namelist_defaults_usr_files.xml"; - push( @nl_defaults_files, $nl_defaults_file ); - $settings{'clm_usr_name'} = $opts{'usrname'}; - $settings{'notest'} = ! $opts{'test'}; - $settings{'csmdata'} = $inputopts{csmdata}; - } else { - my @files = ( "$cfgdir/namelist_files/namelist_defaults_ctsm.xml", - "$cfgdir/namelist_files/namelist_defaults_ctsm_tools.xml", - "$cfgdir/namelist_files/namelist_defaults_drv.xml", - "$cfgdir/namelist_files/namelist_defaults_drydep.xml", - ); - push( @nl_defaults_files, @files ); - } - if ( ! $exitearly ) { - $inputopts{files} = \@nl_defaults_files; - - my $defaults_ref = &queryDefaultXML::ReadDefaultXMLFile( \%inputopts, \%settings ); - my %defaults = %$defaults_ref; - my @keys = keys(%defaults); - if ( defined($opts{'demand'}) && ($#keys == -1) ) { - die "($ProgName $cmdline) ERROR:: demand option is set and nothing was found.\n"; - } - my $print; - foreach my $var ( @keys ) { - $print = 1; - my $value = $defaults{$var}{value}; - my $isadir = $defaults{$var}{isdir}; - my $isafile = $defaults{$var}{isfile}; - my $isastr = $defaults{$var}{isstr}; - # If onlyfiles option set do NOT print if is NOT a file - if ( defined($opts{'onlyfiles'}) && (! $isafile) ) { - $print = undef; - } - # If is a directory - if ( $isadir ) { - # Test that this directory exists - if ( defined($opts{'test'}) && defined($print) ) { - print "Test that directory $value exists\n" if $printing; - if ( ! -d "$value" ) { - die "($ProgName) ERROR:: directory $value does NOT exist!\n"; - } - } - } - # If is a file - if ( $isafile ) { - # Test that this file exists - if ( defined($opts{'test'}) && defined($print) ) { - chomp( $value ); - print "Test that file $value exists\n" if $printing; - if ( ! -f "$value" ) { - die "($ProgName) ERROR:: file $value does NOT exist!\n"; - } - } - } - # If a string - if ( (! defined($opts{'justvalues'}) ) && ($isastr) ) { - $value = "\'$value\'"; - } - # if you just want the filename -- not the full path with the directory - if ( defined($opts{'fileonly'}) ) { - $value =~ s!(.*)/!!; - } - if ( defined($print) ) { - if ( ! defined($opts{'justvalues'}) ) { - print "$var = "; - } - print "$value\n"; - } - } - } - if ( $printing && defined($opts{'test'}) ) { - print "\n\nTesting was successful\n\n" - } - diff --git a/bld/queryDefaultXML.pm b/bld/queryDefaultXML.pm deleted file mode 100644 index 85a81d8f9a..0000000000 --- a/bld/queryDefaultXML.pm +++ /dev/null @@ -1,161 +0,0 @@ -#======================================================================= -# -# This is a perl module to read in a list of namelist_default files. -# -#======================================================================= -use strict; -use Build::Config; -use Build::NamelistDefinition; -use Build::NamelistDefaults; -use Build::Namelist; - -package queryDefaultXML; - -#------------------------------------------------------------------------------- - -sub read_cfg_file -# -# Read in the configuration cache XML file on the build-time configuration -# -{ - my ($file, $empty_cfg_file, $printing, $settings_ref) = @_; - - my $cfg; - my %config; - if ( $file eq "noconfig" ) { - print "No configuration cache file to read in.\n" if $printing; - $cfg = Build::Config->new( $empty_cfg_file ); - } elsif ( -f "$file" ) { - $cfg = Build::Config->new($file); - } else { - die "Bad filename entered: $file does NOT exist or can not open it.\n"; - } - # - # Make sure variables are set to valid values - # - foreach my $key ( keys( %config ) ) { - if ( $cfg->is_valid_name( $key ) ) { - $cfg->set( $key, $config{$key} ); - } - } - foreach my $key ( $cfg->get_names( ) ) { - if ( defined($$settings_ref{$key}) ) { - if ( $cfg->is_valid_name( $key ) ) { - $cfg->set( $key, $$settings_ref{$key} ); - } - } - } - return( $cfg ); -} - -#------------------------------------------------------------------------------- - -sub ReadDefaultXMLFile { -# -# Read in the default XML file for the default namelist settings -# - my $opts_ref = shift; - my $settings_ref = shift; - - # Error check that input and opts hash has the expected variables - my $ProgName = $$opts_ref{'ProgName'}; - my $nm = "${ProgName}::ReadDefaultXMLFile"; - my @required_list = ( "files", "nldef_files", "empty_cfg_file", "config", "namelist", - "csmdata", "hgrid", "printing", "ProgName", "cmdline", - "cfgdir" ); - foreach my $var ( @required_list ) { - if ( ! defined($$opts_ref{$var}) ) { - die "ERROR($nm): Required input variable $var was not found\n"; - } - } - my $printing = $$opts_ref{'printing'}; - my $cmdline = $$opts_ref{'cmdline'}; - # Initialize some local variables - my $files_ref = $$opts_ref{'files'}; - my @files = @$files_ref; - my $nldef_ref = $$opts_ref{'nldef_files'}; - my @nl_definition_files= @$nldef_ref; - my $empty_config_file = $$opts_ref{'empty_cfg_file'}; - my $namelist = $$opts_ref{'namelist'}; - - my $cfg = read_cfg_file( $$opts_ref{'config'}, $$opts_ref{'empty_cfg_file'}, - $printing, $settings_ref ); - - # - # Set up options to send to namelist defaults object - # - my %nlopts; - foreach my $var ( keys( %$settings_ref) ) { - if ( $var ne "csmdata" ) { - $nlopts{$var} = $$settings_ref{$var}; - } - } - if ( $$opts_ref{'hgrid'} ne "any" ) { - $nlopts{'hgrid'} = $$opts_ref{'hgrid'}; - } - # - # Loop through all variables in files - # - print "($nm) Read: $files[0]\n" if $printing; - my %defaults; - my $nldefaults = Build::NamelistDefaults->new($files[0], $cfg); - for ( my $i = 1; $i <= $#files; $i++ ) { - print "($nm) Read: $files[$i]\n" if $printing; - $nldefaults->add( $files[$i] ); - } - my $definition = Build::NamelistDefinition->new( $nl_definition_files[0] ); - for ( my $i = 1; $i <= $#nl_definition_files; $i++ ) { - print "($nm) Read: $nl_definition_files[$i]\n" if $printing; - $definition->add( $nl_definition_files[$i] ); - } - if ( $$opts_ref{'csmdata'} eq "default" ) { - $$opts_ref{'csmdata'} = $nldefaults->get_value( "csmdata", \%nlopts ); - } - $nlopts{'csmdata'} = $$opts_ref{'csmdata'}; - foreach my $name ( $nldefaults->get_variable_names() ) { - my $value = $nldefaults->get_value( $name, \%nlopts ); - if ( $value eq "null" ) { next; } - if ( defined($$settings_ref{'var'}) ) { - if ( $name ne $$settings_ref{'var'} ) { next; } - } - $value =~ s/\n//g; - my $isafile = 0; - if ( $definition->is_input_pathname($name) ) { - - if ( defined($$settings_ref{'clm_usr_name'}) ) { - $value = $nldefaults->get_usr_file( $name, $definition, \%nlopts ); - } - if ( $value && ($value !~ /^\/.+$/) ) { - $value = $$opts_ref{'csmdata'} . "/" . $value; - } - $isafile = 1; - } - my $isadir = 0; - my $isastr = 0; - if ( $definition->get_str_len($name) > 0 ) { - $isastr = 1; - } - # - # If is a directory (is a file and csmdata or a var with dir in name) - # - if ( $isafile && (($name eq "csmdata") || ($name =~ /dir/)) ) { - if ( $name eq "csmdata" ) { - $value = $$opts_ref{'csmdata'}; - $isadir = 1; - } else { - $isadir = 1; - } - } - # Return hash with the results - my $group = $definition->get_group_name( $name ); - if ( $group eq $namelist && $value && (! exists($defaults{$name}{'value'})) ) { - $defaults{$name}{'value'} = $value; - $defaults{$name}{'isfile'} = $isafile; - $defaults{$name}{'isdir'} = $isadir; - $defaults{$name}{'isstr'} = $isastr; - } - } - return( \%defaults ); -} - -1 # To make use or require happy diff --git a/bld/unit_testers/build-namelist_test.pl b/bld/unit_testers/build-namelist_test.pl index f207053924..c8875090cd 100755 --- a/bld/unit_testers/build-namelist_test.pl +++ b/bld/unit_testers/build-namelist_test.pl @@ -78,7 +78,7 @@ sub make_config_cache { -Specifies clm physics +Specifies clm physics EOF $fh->close(); @@ -163,10 +163,10 @@ sub cat_and_create_namelistinfile { # # Figure out number of tests that will run # -my $ntests = 1611; +my $ntests = 2511; if ( defined($opts{'compare'}) ) { - $ntests += 945; + $ntests += 1545; } plan( tests=>$ntests ); @@ -189,7 +189,7 @@ sub cat_and_create_namelistinfile { my $mode = "-phys $phys"; &make_config_cache($phys); -my $DOMFILE = "$inputdata_rootdir/atm/datm7/domain.lnd.T31_gx3v7.090928.nc"; +my $DOMFILE = "$inputdata_rootdir/atm/datm7/domain.lnd.fv0.9x1.25_gx1v6.090309.nc"; my $bldnml = "../build-namelist -verbose -csmdata $inputdata_rootdir -configuration clm -structure standard -glc_nec 10 -no-note"; if ( $opts{'test'} ) { $bldnml .= " -test"; @@ -259,7 +259,7 @@ sub cat_and_create_namelistinfile { # Exercise a bunch of options my $options = "-co2_ppmv 250 "; - $options .= " -res 0.9x1.25 -ssp_rcp SSP1-2.6 -envxml_dir ."; + $options .= " -res 10x15 -ssp_rcp SSP2-4.5 -envxml_dir ."; &make_env_run(); eval{ system( "$bldnml $options > $tempfile 2>&1 " ); }; @@ -319,7 +319,7 @@ sub cat_and_create_namelistinfile { # configuration, structure, irrigate, verbose, clm_demand, ssp_rcp, test, sim_year, use_case foreach my $options ( "-res 0.9x1.25 -configuration nwp", "-res 0.9x1.25 -structure fast", - "-res 0.9x1.25 -namelist '&a irrigate=.true./'", "-res 0.9x1.25 -verbose", "-res 0.9x1.25 -ssp_rcp SSP1-2.6", "-res 0.9x1.25 -test", "-res 0.9x1.25 -sim_year 1850", + "-res 0.9x1.25 -namelist '&a irrigate=.true./'", "-res 0.9x1.25 -verbose", "-res 0.9x1.25 -ssp_rcp SSP2-4.5", "-res 0.9x1.25 -test", "-res 0.9x1.25 -sim_year 1850", "-res 0.9x1.25 -namelist '&a use_lai_streams=.true.,use_soil_moisture_streams=.true./'", "-res 0.9x1.25 -namelist '&a use_excess_ice=.true. use_excess_ice_streams=.true./'", "-res 0.9x1.25 -namelist '&a use_excess_ice=.true. use_excess_ice_streams=.false./'", @@ -366,7 +366,7 @@ sub cat_and_create_namelistinfile { print "\n===============================================================================\n"; print "Test the NEON sites\n"; print "=================================================================================\n"; -my $phys = "clm5_1"; +my $phys = "clm6_0"; $mode = "-phys $phys"; &make_config_cache($phys); my $neondir = "../../cime_config/usermods_dirs/NEON"; @@ -420,17 +420,17 @@ sub cat_and_create_namelistinfile { $mode = "-phys $phys"; &make_config_cache($phys); foreach my $options ( - "-res ne0np4.ARCTIC.ne30x4 -bgc sp -use_case 20thC_transient -namelist '&a start_ymd=19790101/' -lnd_tuning_mode ${phys}_cam6.0", - "-res ne0np4.ARCTICGRIS.ne30x8 -bgc sp -use_case 20thC_transient -namelist '&a start_ymd=19790101/' -lnd_tuning_mode ${phys}_cam6.0", + "-res ne0np4.ARCTIC.ne30x4 -bgc sp -use_case 2000_control -namelist '&a start_ymd=19790101/' -lnd_tuning_mode ${phys}_cam6.0", + "-res ne0np4.ARCTICGRIS.ne30x8 -bgc sp -use_case 1850_control -namelist '&a start_ymd=19790101/' -lnd_tuning_mode ${phys}_cam6.0", "-res 1.9x2.5 -bgc sp -use_case 20thC_transient -namelist '&a start_ymd=19790101/' -lnd_tuning_mode ${phys}_cam6.0", "-res 0.9x1.25 -bgc sp -use_case 20thC_transient -namelist '&a start_ymd=19790101/' -lnd_tuning_mode ${phys}_cam6.0", "-res 0.9x1.25 -bgc bgc -crop -use_case 20thC_transient -namelist '&a start_ymd=19500101/' -lnd_tuning_mode ${phys}_cam6.0", - "-res ne0np4CONUS.ne30x8 -bgc sp -use_case 20thC_transient -namelist '&a start_ymd=20130101/' -lnd_tuning_mode ${phys}_cam6.0", + "-res ne0np4CONUS.ne30x8 -bgc sp -use_case 2000_control -namelist '&a start_ymd=20130101/' -lnd_tuning_mode ${phys}_cam6.0", "-res 1.9x2.5 -bgc sp -use_case 20thC_transient -namelist '&a start_ymd=20030101/' -lnd_tuning_mode ${phys}_cam6.0", "-res 1.9x2.5 -bgc sp -use_case 2010_control -namelist '&a start_ymd=20100101/' -lnd_tuning_mode ${phys}_cam6.0", - "-res 1x1_brazil -bgc fates -no-megan -use_case 2000_control -lnd_tuning_mode ${phys}_CRUv7", - "-res C192 -bgc sp -use_case 2010_control -namelist '&a start_ymd=20100101/' -lnd_tuning_mode ${phys}_cam6.0", - "-res ne0np4.ARCTIC.ne30x4 -bgc sp -use_case 20thC_transient -namelist '&a start_ymd=20130101/' -lnd_tuning_mode ${phys}_cam6.0", + "-res 1x1_brazil -no-megan -use_case 2000_control -lnd_tuning_mode ${phys}_CRUv7", + "-res C96 -bgc sp -use_case 2010_control -namelist '&a start_ymd=20100101/' -lnd_tuning_mode ${phys}_cam6.0", + "-res ne0np4.ARCTIC.ne30x4 -bgc sp -use_case 2000_control -namelist '&a start_ymd=20130101/' -lnd_tuning_mode ${phys}_cam6.0", ) { &make_env_run(); eval{ system( "$bldnml -envxml_dir . $options > $tempfile 2>&1 " ); }; @@ -456,14 +456,12 @@ sub cat_and_create_namelistinfile { $mode = "-phys $phys"; &make_config_cache($phys); foreach my $options ( - "-bgc bgc -use_case 1850-2100_SSP1-2.6_transient -namelist '&a start_ymd=20100101/'", - "-bgc sp -use_case 1850-2100_SSP2-4.5_transient -namelist '&a start_ymd=18501223/'", - "-bgc bgc -use_case 1850-2100_SSP3-7.0_transient -namelist '&a start_ymd=20701029/'", + "--res 0.9x1.25 --bgc sp --use_case 1850-2100_SSP2-4.5_transient --namelist '&a start_ymd=18501223/'", "-bgc fates -use_case 2000_control -no-megan", "-bgc fates -use_case 20thC_transient -no-megan", "-bgc fates -use_case 1850_control -no-megan -namelist \"&a use_fates_sp=T, soil_decomp_method='None'/\"", "-bgc sp -use_case 2000_control -res 0.9x1.25 -namelist '&a use_soil_moisture_streams = T/'", - "-bgc bgc -use_case 1850-2100_SSP5-8.5_transient -namelist '&a start_ymd=19101023/'", + "--res 1.9x2.5 --bgc bgc --use_case 1850-2100_SSP2-4.5_transient --namelist '&a start_ymd=19101023/'", "-namelist \"&a dust_emis_method='Zender_2003', zender_soil_erod_source='lnd' /'\"", "-bgc bgc -use_case 2000_control -namelist \"&a fire_method='nofire'/\" -crop", "-res 0.9x1.25 -bgc sp -use_case 1850_noanthro_control -drydep -fire_emis", @@ -578,7 +576,7 @@ sub cat_and_create_namelistinfile { "onset_threh w SP" =>{ options=>" -envxml_dir . -bgc sp", namelst=>"onset_thresh_depends_on_veg=.true.", GLC_TWO_WAY_COUPLING=>"FALSE", - phys=>"clm5_1", + phys=>"clm6_0", }, "dribble_crphrv w/o CN" =>{ options=>" -envxml_dir . -bgc sp", namelst=>"dribble_crophrv_xsmrpool_2atm=.true.", @@ -718,7 +716,7 @@ sub cat_and_create_namelistinfile { "NEONlightresButGlobal" =>{ options=>"--res 4x5 --bgc bgc --envxml_dir . --light_res 106x740", namelst=>"", GLC_TWO_WAY_COUPLING=>"FALSE", - phys=>"clm5_1", + phys=>"clm6_0", }, "spno-fire" =>{ options=>"-bgc sp -envxml_dir . -use_case 2000_control", namelst=>"fire_method='nofire'", @@ -908,27 +906,27 @@ sub cat_and_create_namelistinfile { "lnd_frac set to UNSET" =>{ options=>"-driver mct -lnd_frac UNSET -envxml_dir .", namelst=>"", GLC_TWO_WAY_COUPLING=>"FALSE", - phys=>"clm5_1", + phys=>"clm6_0", }, "lnd_frac set but nuopc" =>{ options=>"-driver nuopc -lnd_frac $DOMFILE -envxml_dir .", namelst=>"", GLC_TWO_WAY_COUPLING=>"FALSE", - phys=>"clm5_1", + phys=>"clm6_0", }, "lnd_frac not set but lilac"=>{ options=>"-driver nuopc -lilac -envxml_dir . -lnd_frac UNSET", namelst=>"fsurdat='surfdata.nc'", GLC_TWO_WAY_COUPLING=>"FALSE", - phys=>"clm5_1", + phys=>"clm6_0", }, "fatmlndfrc set but nuopc" =>{ options=>"-driver nuopc -envxml_dir .", namelst=>"fatmlndfrc='frac.nc'", GLC_TWO_WAY_COUPLING=>"FALSE", - phys=>"clm5_1", + phys=>"clm6_0", }, "force_send but not nuopc" =>{ options=>"-driver mct -lnd_frac $DOMFILE -envxml_dir .", namelst=>"force_send_to_atm = .false.", GLC_TWO_WAY_COUPLING=>"FALSE", - phys=>"clm5_1", + phys=>"clm6_0", }, "branch but NO nrevsn" =>{ options=>"-clm_start_type branch -envxml_dir .", namelst=>"", @@ -968,7 +966,7 @@ sub cat_and_create_namelistinfile { "useFATESWcrop" =>{ options=>"-bgc fates -envxml_dir . -no-megan -crop", namelst=>"", GLC_TWO_WAY_COUPLING=>"FALSE", - phys=>"clm5_1", + phys=>"clm6_0", }, "useFATESWcreatecrop" =>{ options=>"-bgc fates -envxml_dir . -no-megan", namelst=>"create_crop_landunit=.true.", @@ -983,37 +981,37 @@ sub cat_and_create_namelistinfile { "useFATESWbMH" =>{ options=>"-bgc fates -envxml_dir . -no-megan", namelst=>"use_biomass_heat_storage=.true.", GLC_TWO_WAY_COUPLING=>"FALSE", - phys=>"clm5_1", + phys=>"clm6_0", }, "FireNoneButFATESfireon" =>{ options=>"-bgc fates -envxml_dir . -no-megan -light_res none", namelst=>"fates_spitfire_mode=4", GLC_TWO_WAY_COUPLING=>"FALSE", - phys=>"clm5_1", + phys=>"clm6_0", }, "FATESwspitfireOffLigtOn" =>{ options=>"-bgc fates -envxml_dir . -no-megan -light_res 360x720", namelst=>"fates_spitfire_mode=0", GLC_TWO_WAY_COUPLING=>"FALSE", - phys=>"clm5_1", + phys=>"clm6_0", }, "useFATESWluna" =>{ options=>"--bgc fates --envxml_dir . --no-megan", namelst=>"use_luna=TRUE", GLC_TWO_WAY_COUPLING=>"FALSE", - phys=>"clm5_1", + phys=>"clm6_0", }, "useFATESWfun" =>{ options=>"--bgc fates --envxml_dir . --no-megan", namelst=>"use_fun=TRUE", GLC_TWO_WAY_COUPLING=>"FALSE", - phys=>"clm5_1", + phys=>"clm6_0", }, "useFATESWOsuplnitro" =>{ options=>"--bgc fates --envxml_dir . --no-megan", namelst=>"suplnitro='NONE'", GLC_TWO_WAY_COUPLING=>"FALSE", - phys=>"clm5_1", + phys=>"clm6_0", }, "FireNoneButBGCfireon" =>{ options=>"-bgc bgc -envxml_dir . -light_res none", namelst=>"fire_method='li2021gswpfrc'", GLC_TWO_WAY_COUPLING=>"FALSE", - phys=>"clm5_1", + phys=>"clm6_0", }, "createcropFalse" =>{ options=>"-bgc bgc -envxml_dir . -no-megan", namelst=>"create_crop_landunit=.false.", @@ -1201,7 +1199,7 @@ sub cat_and_create_namelistinfile { phys=>"clm5_0", }, "NOlunabutsetJmaxb1" =>{ options=>"-envxml_dir . -bgc sp", - namelst=>"use_luna=.fwlse., jmaxb1=1.0", + namelst=>"use_luna=.false., jmaxb1=1.0", GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, @@ -1291,7 +1289,7 @@ sub cat_and_create_namelistinfile { "methane off W nitrif_denit"=>{ options=>"-bgc bgc -envxml_dir .", namelst=>"use_nitrif_denitrif=.true.,use_lch4=.false.", GLC_TWO_WAY_COUPLING=>"FALSE", - phys=>"clm5_1", + phys=>"clm6_0", }, "soilm_stream w transient" =>{ options=>"-res 0.9x1.25 -envxml_dir . -use_case 20thC_transient", namelst=>"use_soil_moisture_streams=T,soilm_tintalgo='linear'", @@ -1311,12 +1309,12 @@ sub cat_and_create_namelistinfile { "FUN_wo_flexCN" =>{ options=>"-envxml_dir . -bgc bgc", namelst=>"use_fun=.true.,use_flexiblecn=.false.", GLC_TWO_WAY_COUPLING=>"FALSE", - phys=>"clm5_1", + phys=>"clm6_0", }, "NotNEONbutNEONlightres" =>{ options=>"--res CLM_USRDAT --clm_usr_name regional --envxml_dir . --bgc bgc --light_res 106x174", namelst=>"fsurdat='build-namelist_test.pl'", GLC_TWO_WAY_COUPLING=>"FALSE", - phys=>"clm5_1", + phys=>"clm6_0", }, ); foreach my $key ( keys(%warntest) ) { @@ -1339,87 +1337,60 @@ sub cat_and_create_namelistinfile { # # Loop over all physics versions # -foreach my $phys ( "clm4_5", "clm5_0", "clm5_1" ) { +foreach my $phys ( "clm4_5", "clm5_0", "clm5_1", "clm6_0" ) { $mode = "-phys $phys"; &make_config_cache($phys); -print "\n==================================================\n"; -print "Test ALL resolutions with SP\n"; -print "==================================================\n"; +print "\n========================================================================\n"; +print "Test ALL resolutions that have surface datasets with SP for 1850 and 2000\n"; +print "========================================================================\n"; # Check for ALL resolutions with CLM50SP -my $reslist = `../queryDefaultNamelist.pl -res list -s`; -my @resolutions = split( / /, $reslist ); +my @resolutions = ( "360x720cru", "10x15", "4x5", "0.9x1.25", "1.9x2.5", "ne3np4.pg3", "ne16np4.pg3", "ne30np4", "ne30np4.pg2", "ne30np4.pg3", "ne120np4.pg3", "ne0np4CONUS.ne30x8", "ne0np4.ARCTIC.ne30x4", "ne0np4.ARCTICGRIS.ne30x8", "C96", "mpasa480", "mpasa120" ); +my @only2000_resolutions = ( "1x1_numaIA", "1x1_brazil", "1x1_mexicocityMEX", "1x1_vancouverCAN", "1x1_urbanc_alpha", "5x5_amazon", "0.125nldas2", "mpasa60", "mpasa15", "mpasa3p75" ); my @regional; foreach my $res ( @resolutions ) { chomp($res); print "=== Test $res === \n"; - my $options = "-res $res -bgc sp -envxml_dir ."; - - # Regional single point resolutions - if ( $res =~ /^([0-9]+x[0-9]+_[a-zA-Z]+)$/ ) { - push( @regional, $res ); - next; - # Resolutions for mksurfdata mapping - } elsif ( $res eq "0.5x0.5" || - $res eq "0.25x0.25" || - $res eq "3x3min" || - $res eq "5x5min" || - $res eq "10x10min" || - $res eq "0.125x0.125" || - $res eq "0.33x0.33" || - $res eq "1km-merge-10min" ) { - next; - # Resolutions that were supported in clm40 but NOT clm45/clm50 - } elsif ( $res eq "ne240np4" || - $res eq "ne60np4" || - $res eq "ne4np4" || - $res eq "2.5x3.33" || - $res eq "0.23x0.31" || - $res eq "0.47x0.63" || - $res eq "94x192" || - $res eq "8x16" || - $res eq "32x64" || - $res eq "128x256" || - $res eq "360x720cru" || - $res eq "512x1024" ) { - next; - # Resolutions not supported on release branch - } elsif ( $res eq "ne120np4" || - $res eq "conus_30_x8" ) { - next; - } + foreach my $use_case ( "1850_control", "2000_control" ) { + # Skip resolutions that only have 2000 versions + if ( ($use_case eq "1850_control") && ($res ~~ @only2000_resolutions) ) { + next; + } + print "=== Test $use_case === \n"; + my $options = "-res $res -bgc sp -envxml_dir . --use_case $use_case"; - &make_env_run(); - eval{ system( "$bldnml $options > $tempfile 2>&1 " ); }; - is( $@, '', "$options" ); + &make_env_run(); + eval{ system( "$bldnml $options > $tempfile 2>&1 " ); }; + is( $@, '', "$options" ); - $cfiles->checkfilesexist( "$options", $mode ); + $cfiles->checkfilesexist( "$options", $mode ); - $cfiles->shownmldiff( "default", "standard" ); - if ( defined($opts{'compare'}) ) { - $cfiles->doNOTdodiffonfile( "$tempfile", "$options", $mode ); - $cfiles->comparefiles( "$options", $mode, $opts{'compare'} ); - } + $cfiles->shownmldiff( "default", "standard" ); + if ( defined($opts{'compare'}) ) { + $cfiles->doNOTdodiffonfile( "$tempfile", "$options", $mode ); + $cfiles->comparefiles( "$options", $mode, $opts{'compare'} ); + } - if ( defined($opts{'generate'}) ) { - $cfiles->copyfiles( "$options", $mode ); + if ( defined($opts{'generate'}) ) { + $cfiles->copyfiles( "$options", $mode ); + } + &cleanup(); print "\n"; } - &cleanup(); print "\n"; } print "\n==================================================\n"; -print " Test important resolutions for BGC\n"; +print " Test important resolutions for BGC and historical\n"; print "==================================================\n"; -my @resolutions = ( "4x5", "10x15", "ne30np4", "ne16np4", "1.9x2.5", "0.9x1.25" ); +my @resolutions = ( "4x5", "10x15", "360x720cru", "ne30np4.pg3", "ne3np4.pg3", "1.9x2.5", "0.9x1.25", "C96", "mpasa120" ); my @regional; my $nlbgcmode = "bgc"; my $mode = "$phys-$nlbgcmode"; foreach my $res ( @resolutions ) { chomp($res); print "=== Test $res === \n"; - my $options = "-res $res -envxml_dir . -bgc $nlbgcmode"; + my $options = "-res $res -envxml_dir . -bgc $nlbgcmode --use_case 20thC_transient"; &make_env_run(); eval{ system( "$bldnml $options > $tempfile 2>&1 " ); }; @@ -1440,7 +1411,7 @@ sub cat_and_create_namelistinfile { } print "\n==================================================\n"; -print " Test all use-cases \n"; +print " Rest all use-cases \n"; print "==================================================\n"; # Run over all use-cases... @@ -1473,7 +1444,23 @@ sub cat_and_create_namelistinfile { print "==================================================\n"; # Check for crop resolutions -my @crop_res = ( "1x1_numaIA", "1x1_smallvilleIA", "4x5", "10x15", "0.9x1.25", "1.9x2.5", "ne30np4" ); +my $crop1850_res = "1x1_smallvilleIA"; +$options = "-bgc bgc -crop -res $crop1850_res -use_case 1850_control -envxml_dir ."; +&make_env_run(); +eval{ system( "$bldnml $options > $tempfile 2>&1 " ); }; +is( $@, '', "$options" ); +$cfiles->checkfilesexist( "$options", $mode ); +$cfiles->shownmldiff( "default", "standard" ); +if ( defined($opts{'compare'}) ) { + $cfiles->doNOTdodiffonfile( "$tempfile", "$options", $mode ); + $cfiles->comparefiles( "$options", $mode, $opts{'compare'} ); +} +if ( defined($opts{'generate'}) ) { + $cfiles->copyfiles( "$options", $mode ); +} +&cleanup(); + +my @crop_res = ( "1x1_numaIA", "4x5", "10x15", "0.9x1.25", "1.9x2.5", "ne3np4.pg3", "ne30np4", "ne30np4.pg3", "C96", "mpasa120" ); foreach my $res ( @crop_res ) { $options = "-bgc bgc -crop -res $res -envxml_dir ."; &make_env_run(); @@ -1506,10 +1493,8 @@ sub cat_and_create_namelistinfile { # cases; I'm not sure if it's actually important to test this with all # of the different use cases. my @glc_res = ( "0.9x1.25", "1.9x2.5" ); -my @use_cases = ( "1850-2100_SSP1-2.6_transient", +my @use_cases = ( "1850-2100_SSP2-4.5_transient", - "1850-2100_SSP3-7.0_transient", - "1850-2100_SSP5-8.5_transient", "1850_control", "2000_control", "2010_control", @@ -1544,7 +1529,7 @@ sub cat_and_create_namelistinfile { } } # Transient 20th Century simulations -my @tran_res = ( "0.9x1.25", "1.9x2.5", "ne30np4", "10x15" ); +my @tran_res = ( "0.9x1.25", "1.9x2.5", "ne30np4.pg3", "10x15" ); my $usecase = "20thC_transient"; my $GLC_NEC = 10; foreach my $res ( @tran_res ) { @@ -1564,15 +1549,9 @@ sub cat_and_create_namelistinfile { &cleanup(); } # Transient ssp_rcp scenarios that work -my @tran_res = ( "0.9x1.25", "1.9x2.5", "10x15" ); -foreach my $usecase ( "1850_control", "1850-2100_SSP5-8.5_transient", "1850-2100_SSP1-2.6_transient", "1850-2100_SSP3-7.0_transient", - "1850-2100_SSP2-4.5_transient" ) { - my $startymd = undef; - if ( $usecase eq "1850_control") { - $startymd = 18500101; - } else { - $startymd = 20150101; - } +my @tran_res = ( "4x5", "0.9x1.25", "1.9x2.5", "10x15", "360x720cru", "ne3np4.pg3", "ne16np4.pg3", "ne30np4.pg3", "C96", "mpasa120" ); +foreach my $usecase ( "1850-2100_SSP2-4.5_transient" ) { + my $startymd = 20150101; foreach my $res ( @tran_res ) { $options = "-res $res -bgc bgc -crop -use_case $usecase -envxml_dir . -namelist '&a start_ymd=$startymd/'"; &make_env_run(); @@ -1594,13 +1573,36 @@ sub cat_and_create_namelistinfile { # # End loop over versions # +# +# Test ALL SSP's for f09... +# +$phys = "clm6_0"; +$mode = "-phys $phys"; +&make_config_cache($phys); +my $res = "0.9x1.25"; +foreach my $usecase ( "1850-2100_SSP5-8.5_transient", "1850-2100_SSP2-4.5_transient", "1850-2100_SSP1-2.6_transient", "1850-2100_SSP3-7.0_transient" ) { + $options = "-res $res -bgc bgc -crop -use_case $usecase -envxml_dir . -namelist '&a start_ymd=20150101/'"; + &make_env_run(); + eval{ system( "$bldnml $options > $tempfile 2>&1 " ); }; + is( $@, '', "$options" ); + $cfiles->checkfilesexist( "$options", $mode ); + $cfiles->shownmldiff( "default", "standard" ); + if ( defined($opts{'compare'}) ) { + $cfiles->doNOTdodiffonfile( "$tempfile", "$options", $mode ); + $cfiles->comparefiles( "$options", $mode, $opts{'compare'} ); + } + if ( defined($opts{'generate'}) ) { + $cfiles->copyfiles( "$options", $mode ); + } + &cleanup(); +} -# The SSP's that fail... +# The SSP's that fail because of missing ndep files... $phys = "clm5_0"; $mode = "-phys $phys"; &make_config_cache($phys); my $res = "0.9x1.25"; -foreach my $usecase ( "1850-2100_SSP4-3.4_transient", "1850-2100_SSP5-3.4_transient", "1850-2100_SSP1-1.9_transient", +foreach my $usecase ( "1850-2100_SSP5-3.4_transient", "1850-2100_SSP4-3.4", "1850-2100_SSP1-1.9_transient", "1850-2100_SSP4-6.0_transient" ) { $options = "-res $res -bgc bgc -crop -use_case $usecase -envxml_dir . -namelist '&a start_ymd=20150101/'"; &make_env_run(); @@ -1610,10 +1612,10 @@ sub cat_and_create_namelistinfile { } print "\n==================================================\n"; -print "Test clm4.5/clm5.0/clm5_1 resolutions \n"; +print "Test clm4.5/clm5.0/clm5_1/clm6_0 resolutions \n"; print "==================================================\n"; -foreach my $phys ( "clm4_5", 'clm5_0', 'clm5_1' ) { +foreach my $phys ( "clm4_5", 'clm5_0', 'clm5_1', "clm6_0" ) { my $mode = "-phys $phys"; &make_config_cache($phys); my @clmoptions = ( "-bgc bgc -envxml_dir .", "-bgc bgc -envxml_dir . -clm_accelerated_spinup=on", "-bgc bgc -envxml_dir . -light_res 360x720", @@ -1621,7 +1623,7 @@ sub cat_and_create_namelistinfile { "-bgc bgc -clm_demand flanduse_timeseries -sim_year 1850-2000 -namelist '&a start_ymd=18500101/'", "-bgc bgc -envxml_dir . -namelist '&a use_c13=.true.,use_c14=.true.,use_c14_bombspike=.true./'" ); foreach my $clmopts ( @clmoptions ) { - my @clmres = ( "10x15", "0.9x1.25", "1.9x2.5" ); + my @clmres = ( "10x15", "4x5", "360x720cru", "0.9x1.25", "1.9x2.5", "ne3np4.pg3", "ne16np4.pg3", "ne30np4.pg3", "C96", "mpasa120" ); foreach my $res ( @clmres ) { $options = "-res $res -envxml_dir . "; &make_env_run( ); @@ -1642,7 +1644,7 @@ sub cat_and_create_namelistinfile { my @clmoptions = ( "-bgc bgc -envxml_dir .", "-bgc sp -envxml_dir .", ); foreach my $clmopts ( @clmoptions ) { - my @clmres = ( "ne16np4" ); + my @clmres = ( "ne16np4.pg3" ); foreach my $res ( @clmres ) { $options = "-res $res -envxml_dir . "; &make_env_run( ); @@ -1678,7 +1680,7 @@ sub cat_and_create_namelistinfile { &cleanup(); # Run FATES mode for several resolutions and configurations my $clmoptions = "-bgc fates -envxml_dir . -no-megan"; - my @clmres = ( "1x1_brazil", "5x5_amazon", "4x5", "1.9x2.5" ); + my @clmres = ( "4x5", "1.9x2.5" ); foreach my $res ( @clmres ) { $options = "-res $res -clm_start_type cold"; my @edoptions = ( "-use_case 2000_control", @@ -1708,23 +1710,25 @@ sub cat_and_create_namelistinfile { } } # -# Run over the differen lnd_tuning modes +# Run over the different lnd_tuning modes # my $res = "0.9x1.25"; -my $mask = "gx1v6"; +my $mask = "gx1v7"; my $simyr = "1850"; -foreach my $phys ( "clm4_5", 'clm5_0', 'clm5_1' ) { +foreach my $phys ( "clm4_5", 'clm5_0', 'clm5_1', 'clm6_0' ) { my $mode = "-phys $phys"; &make_config_cache($phys); my @forclist = (); - if ( $phys == "clm5_1" ) { - @forclist = ( "GSWP3v1", "cam6.0", "cam5.0", "cam4.0" ); - } else { - @forclist = ( "CRUv7", "GSWP3v1", "cam6.0", "cam5.0", "cam4.0" ); - } + @forclist = ( "CRUv7", "GSWP3v1", "cam6.0", "cam5.0", "cam4.0" ); foreach my $forc ( @forclist ) { foreach my $bgc ( "sp", "bgc" ) { my $lndtuningmode = "${phys}_${forc}"; + if ( $lndtuningmode eq "clm5_1_CRUv7" ) { + next; + } + if ( $lndtuningmode eq "clm6_0_CRUv7" ) { + next; + } my $clmoptions = "-res $res -mask $mask -sim_year $simyr -envxml_dir . -lnd_tuning_mod $lndtuningmode -bgc $bgc"; &make_env_run( ); eval{ system( "$bldnml $clmoptions > $tempfile 2>&1 " ); }; diff --git a/cime_config/SystemTests/mksurfdataesmf.py b/cime_config/SystemTests/mksurfdataesmf.py new file mode 100644 index 0000000000..3a083bc724 --- /dev/null +++ b/cime_config/SystemTests/mksurfdataesmf.py @@ -0,0 +1,156 @@ +""" +This test passes if mksurfdata_esmf generates an fsurdat (surface dataset) +and the CTSM completes a simulation with this fsurdat file. + +We test res = '10x15' because it uses a lower-res topography file instead of +the 1-km topography raw dataset. The 1-km file causes the test to run out of +memory on cheyenne. + +Currently casper complains that `git -C` is not a valid option. +I added -C to the `git describe` in gen_mksurfdata_namelist for this +system test to work. +""" +import os +import sys +import subprocess +from datetime import datetime +from CIME.SystemTests.system_tests_common import SystemTestsCommon +from CIME.XML.standard_module_setup import * +from CIME.SystemTests.test_utils.user_nl_utils import append_to_user_nl_files + +logger = logging.getLogger(__name__) + + +class MKSURFDATAESMF(SystemTestsCommon): + def __init__(self, case): + """ + initialize an object interface to the SMS system test + """ + SystemTestsCommon.__init__(self, case) + + # Paths and strings needed throughout + ctsm_root = self._case.get_value("COMP_ROOT_DIR_LND") + self._tool_path = os.path.join(ctsm_root, "tools/mksurfdata_esmf") + self._tool_bld = os.path.join(self._get_caseroot(), "tool_bld") + time_stamp = datetime.today().strftime("%y%m%d") + self._res = "10x15" # see important comment in script's docstring + self._model_yr = "1850" + self._jobscript = os.path.join( + self._get_caseroot(), "mksurfdataesmf_test_jobscript_single.sh" + ) + self._fsurdat_namelist = os.path.join( + self._get_caseroot(), + f"surfdata_{self._res}_hist_{self._model_yr}_78pfts_c{time_stamp}.namelist", + ) + self._fsurdat_nc = os.path.join( + self._get_caseroot(), + f"surfdata_{self._res}_hist_{self._model_yr}_78pfts_c{time_stamp}.nc", + ) + self._TestStatus_log_path = os.path.join(self._get_caseroot(), "TestStatus.log") + + def build_phase(self, sharedlib_only=False, model_only=False): + """ + Build executable that will generate fsurdat + Generate namelist for generating fsurdat + Generate jobscript that runs executable + Modify user_nl_clm to point to the generated fsurdat + """ + # build_phase gets called twice: + # - once with sharedlib_only = True and + # - once with model_only = True + # Call the following steps only once during the test but do not skip + # if the test stops and gets restarted. + if sharedlib_only: + # Paths and strings + build_script_path = os.path.join(self._tool_path, "gen_mksurfdata_build") + nml_script_path = os.path.join(self._tool_path, "gen_mksurfdata_namelist") + gen_jobscript_path = os.path.join(self._tool_path, "gen_mksurfdata_jobscript_single") + gen_mksurfdata_namelist = f"{nml_script_path} --res {self._res} --start-year {self._model_yr} --end-year {self._model_yr}" + + if not os.path.exists(nml_script_path): + sys.exit(f"ERROR The build naemlist script {nml_script_path} does NOT exist") + + if not os.path.exists(gen_jobscript_path): + sys.exit(f"ERROR The jobscript script {gen_jobscript_path} does NOT exist") + + gen_mksurfdata_jobscript = ( + f"{gen_jobscript_path} --number-of-nodes 1 --tasks-per-node 64 --namelist-file " + + f"{self._fsurdat_namelist} --bld-path {self._tool_bld} --jobscript-file {self._jobscript}" + ) + if not os.path.exists(build_script_path): + sys.exit(f"ERROR The build script {build_script_path} does NOT exist") + + # Rm tool_bld and build executable that will generate fsurdat + try: + subprocess.check_call(f"rm -rf {self._tool_bld}", shell=True) + except subprocess.CalledProcessError as e: + sys.exit( + f"{e} ERROR REMOVING {self._tool_bld}. DETAILS IN {self._TestStatus_log_path}" + ) + try: + subprocess.check_call(f"{build_script_path} --blddir {self._tool_bld}", shell=True) + except subprocess.CalledProcessError as e: + print(f"build directory = {self._tool_bld}\n") + sys.exit( + f"{e} ERROR RUNNING {build_script_path} DETAILS IN {self._TestStatus_log_path}" + ) + + # Generate namelist for generating fsurdat (rm namelist if exists) + if os.path.exists(self._fsurdat_namelist): + os.remove(self._fsurdat_namelist) + try: + subprocess.check_call(gen_mksurfdata_namelist, shell=True) + except subprocess.CalledProcessError as e: + sys.exit( + f"{e} ERROR RUNNING {gen_mksurfdata_namelist}. DETAILS IN {self._TestStatus_log_path}" + ) + + # Generate jobscript that will run the executable + if os.path.exists(self._jobscript): + os.remove(self._jobscript) + try: + subprocess.check_call(gen_mksurfdata_jobscript, shell=True) + except subprocess.CalledProcessError as e: + sys.exit( + f"{e} ERROR RUNNING {gen_mksurfdata_jobscript}. DETAILS IN {self._TestStatus_log_path}" + ) + # Change self._jobscript to an executable file + subprocess.check_call(f"chmod a+x {self._jobscript}", shell=True) + + # Call this step only once even if the test stops and gets restarted. + if not os.path.exists(os.path.join(self._get_caseroot(), "done_MKSURFDATAESMF_setup.txt")): + # Modify user_nl_clm to point to the generated fsurdat + self._modify_user_nl() + with open("done_MKSURFDATAESMF_setup.txt", "w") as fp: + pass + + self.build_indv(sharedlib_only=sharedlib_only, model_only=model_only) + + def run_phase(self): + """ + Run executable to generate fsurdat + Submit CTSM run that uses fsurdat just generated + """ + + # Run executable to generate fsurdat (rm fsurdat if exists) + if os.path.exists(self._fsurdat_nc): + os.remove(self._fsurdat_nc) + try: + subprocess.check_call(self._jobscript, shell=True) + except subprocess.CalledProcessError as e: + sys.exit(f"{e} ERROR RUNNING {self._jobscript}; details in {self._TestStatus_log_path}") + + # Submit CTSM run that uses fsurdat just generated + self.run_indv() + + def _modify_user_nl(self): + """ + Modify user_nl_clm to point to the generated fsurdat + """ + append_to_user_nl_files( + caseroot=self._get_caseroot(), + component="clm", + contents="fsurdat = '{}'".format(self._fsurdat_nc) + + "\n" + + "convert_ocean_to_land = .true.", + ) diff --git a/cime_config/SystemTests/rxcropmaturity.py b/cime_config/SystemTests/rxcropmaturity.py index 5d3b07bfbf..acb63bb000 100644 --- a/cime_config/SystemTests/rxcropmaturity.py +++ b/cime_config/SystemTests/rxcropmaturity.py @@ -328,6 +328,7 @@ def _create_config_file_evenlysplitcrop(self): cfg_out.write("PCT_GLACIER = 0.0\n") cfg_out.write("PCT_WETLAND = 0.0\n") cfg_out.write("PCT_LAKE = 0.0\n") + cfg_out.write("PCT_OCEAN = 0.0\n") cfg_out.write("PCT_URBAN = 0.0 0.0 0.0\n") def _run_check_rxboth_run(self): diff --git a/cime_config/buildnml b/cime_config/buildnml index f09c45e703..8e93b77015 100755 --- a/cime_config/buildnml +++ b/cime_config/buildnml @@ -23,7 +23,7 @@ _config_cache_template = """ -Specifies CTSM physics +Specifies CTSM physics """ @@ -78,6 +78,70 @@ def buildnml(case, caseroot, compname): "The -namelist option is NOT allowed to be part of CLM_BLDNML_OPTS, " + "use the CLM_NAMELIST_OPTS option or add namelist items to user_nl_clm instead ", ) + # + # Warnings for land tuning modes + # + closest_tuning = { + "clm4_5_1PT": "clm4_5_CRUv7", + "clm4_5_QIAN": "clm4_5_CRUv7", + "clm4_5_NLDAS2": "clm4_5_CRUv7", + "clm4_5_ERA5": "clm4_5_CRUv7", + "clm5_0_1PT": "clm5_0_GSWP3v1", + "clm5_0_QIAN": "clm5_0_GSWP3v1", + "clm5_0_NLDAS2": "clm5_0_GSWP3v1", + "clm5_0_ERA5": "clm5_0_GSWP3v1", + "clm5_1_1PT": "clm5_1_GSWP3v1", + "clm5_1_QIAN": "clm5_1_GSWP3v1", + "clm5_1_NLDAS2": "clm5_1_GSWP3v1", + "clm5_1_ERA5": "clm5_1_GSWP3v1", + "clm5_1_CRUv7": "clm5_1_GSWP3v1", + "clm6_0_1PT": "clm6_0_GSWP3v1", + "clm6_0_QIAN": "clm6_0_GSWP3v1", + "clm6_0_NLDAS2": "clm6_0_GSWP3v1", + "clm6_0_ERA5": "clm6_0_GSWP3v1", + "clm6_0_CRUv7": "clm6_0_GSWP3v1", + } + for mode, closest in closest_tuning.items(): + if lnd_tuning_mode == mode: + logger.warning( + "IMPORTANT NOTE: LND_TUNING_MODE is " + + lnd_tuning_mode + + " which does NOT have tuned settings, so using the closest option which is " + + closest + ) + logger.warning( + " : To suppress this message explicitly set LND_TUNING_MODE=" + + lnd_tuning_mode + + " for your case" + ) + lnd_tuning_mode = closest + + # CAM4 and CAM5 options are based on cam6 tuning + # (other than the Zender dust emission soil eroditability file which is specific + # to the CAM version) + tuning_based_on = { + "clm6_0_GSWP3v1": "clm5_0_GSWP3v1", + "clm5_1_GSWP3v1": "clm5_0_GSWP3v1", + "clm6_0_cam6.0": "clm5_0_cam6.0", + "clm6_0_cam5.0": "clm5_0_cam6.0", + "clm6_0_cam4.0": "clm5_0_cam6.0", + "clm5_1_cam6.0": "clm5_0_cam6.0", + "clm5_1_cam5.0": "clm5_0_cam6.0", + "clm5_1_cam4.0": "clm5_0_cam6.0", + "clm5_0_cam5.0": "clm5_0_cam6.0", + "clm5_0_cam4.0": "clm5_0_cam6.0", + "clm4_5_cam6.0": "clm5_0_cam6.0", + "clm4_5_cam5.0": "clm5_0_cam6.0", + "clm4_5_cam4.0": "clm5_0_cam6.0", + } + for mode, based_on in tuning_based_on.items(): + if lnd_tuning_mode == mode: + logger.warning( + "NOTE: LND_TUNING_MODE is " + + lnd_tuning_mode + + " which is NOT tuned, but is based on " + + based_on + ) # ----------------------------------------------------- # Set ctsmconf diff --git a/cime_config/config_component.xml b/cime_config/config_component.xml index 8fecd2f17b..f7adab268f 100644 --- a/cime_config/config_component.xml +++ b/cime_config/config_component.xml @@ -1,4 +1,3 @@ - @@ -17,6 +16,7 @@ clm4.5: clm5.0: clm5.1: + clm6.0: Satellite phenology: Satellite phenology with VIC hydrology: @@ -61,38 +61,89 @@ run_component_ctsm env_run.xml Tuning parameters and initial conditions should be optimized for what CLM model version and what meteorlogical forcing combination? + Options for all combinations of CLM physics and atm forcing are given. The buildnml and namelist_defaults will narrow it down to the ones + that have been tuned. The buildnml will also warn you if a tuning combination is based on another set. + Atm forcing options: + CRUv7 + GSWP3 + CAM4.0 + CAM5.0 + CAM6.0 + CAM7.0 + QIAN (not tuned) + 1PT (not tuned) + NLDAS2 (not tuned) + ERA5 (not tuned) + Other atm forcing options are invalid to run CLM and will result in an error. UNSET - clm5_0_cam6.0,clm5.0_cam5.0,clm5.0_cam4.0,clm5_0_GSWP3v1,clm5_0_CRUv7,clm4_5_CRUv7,clm4_5_GSWP3v1,clm4_5_cam6.0,clm4_5_cam5.0,clm4_5_cam4.0,clm5_1_GSWP3v1,clm5_1_cam6.0,clm5_1_cam5.0,clm5_1_cam4.0 - - clm4_5_CRUv7 - clm4_5_CRUv7 - clm4_5_GSWP3v1 - clm4_5_cam4.0 - clm4_5_cam5.0 - clm4_5_cam6.0 - clm4_5_cam6.0 - clm4_5_cam6.0 - clm5_0_CRUv7 - clm5_0_CRUv7 - clm5_0_GSWP3v1 - clm5_0_cam4.0 - clm5_0_cam5.0 - clm5_0_cam6.0 - clm5_0_cam6.0 - clm5_0_cam6.0 - clm5_1_cam4.0 - clm5_1_cam5.0 - clm5_1_cam6.0 - clm5_1_cam6.0 - clm5_1_GSWP3v1 - clm5_1_cam6.0 + + clm5_0_cam6.0,clm5_0_cam7.0,clm5.0_cam5.0,clm5.0_cam4.0,clm5_0_GSWP3v1,clm5_0_CRUv7,clm5_0_QIAN,clm5_0_1PT,clm5_0_NLDAS2,clm5_0_ERA5,clm4_5_CRUv7,clm4_5_GSWP3v1,clm4_5_QIAN,clm4_5_cam6.0,clm4_5_cam7.0,clm4_5_cam5.0,clm4_5_cam4.0,clm4_5_1PT,clm4_5_NLDAS2,clm4_5_ERA5,clm5_1_CRUv7,clm5_1_GSWP3v1,clm5_1_cam6.0,clm5_1_QIAN,clm5_1_1PT,clm5_1_NLDAS2,clm5_1_ERA5,clm6_0_CRUv7,clm6_0_GSWP3v1,clm6_0_cam6.0,clm6_0_cam7.0,clm6_0_cam5.0,clm6_0_cam4.0,clm6_0_QIAN,clm6_0_1PT,clm6_0_NLDAS2,clm6_0_ERA5 + + + + clm4_5_CRUv7 + clm4_5_CRUv7 + clm4_5_CRUv7 + clm4_5_GSWP3v1 + clm4_5_cam6.0 + clm4_5_cam4.0 + clm4_5_cam5.0 + clm4_5_cam7.0 + clm4_5_cam6.0 + clm4_5_QIAN + clm4_5_QIAN + clm4_5_1PT + clm4_5_NLDAS2 + clm4_5_ERA5 + + clm5_0_CRUv7 + clm5_0_CRUv7 + clm5_0_GSWP3v1 + clm5_0_GSWP3v1 + clm5_0_cam6.0 + clm5_0_cam4.0 + clm5_0_cam5.0 + clm5_0_cam7.0 + clm5_0_cam6.0 + clm5_0_QIAN + clm5_0_QIAN + clm5_0_1PT + clm5_0_NLDAS2 + clm5_0_ERA5 + + clm5_1_GSWP3v1 + clm5_1_GSWP3v1 + clm5_1_cam6.0 + clm5_1_cam4.0 + clm5_1_cam5.0 + clm5_1_cam6.0 + + clm6_0_CRUv7 + clm6_0_CRUv7 + clm6_0_GSWP3v1 + clm6_0_GSWP3v1 + clm6_0_cam6.0 + clm6_0_cam4.0 + clm6_0_cam5.0 + clm6_0_cam7.0 + clm6_0_cam6.0 + clm6_0_QIAN + clm6_0_QIAN + clm6_0_1PT + clm6_0_NLDAS2 + clm6_0_ERA5 + + INVALID_DATM_FORCING_FOR_RUNNING_CTSM + INVALID_DATM_FORCING_FOR_RUNNING_CTSM + INVALID_DATM_FORCING_FOR_RUNNING_CTSM + INVALID_DATM_FORCING_FOR_RUNNING_CTSM char - clm4_5,clm5_0,clm5_1 + clm4_5,clm5_0,clm5_1,clm6_0 - I1PtClm51Bgc - 2000_DATM%1PT_CLM51%BGC_SICE_SOCN_SROF_SGLC_SWAV + I1PtClm60Bgc + 2000_DATM%1PT_CLM60%BGC_SICE_SOCN_SROF_SGLC_SWAV - I1PtClm51Fates - 2000_DATM%1PT_CLM51%FATES_SICE_SOCN_SROF_SGLC_SWAV + I1PtClm60Fates + 2000_DATM%1PT_CLM60%FATES_SICE_SOCN_SROF_SGLC_SWAV - IHist1PtClm51Bgc - HIST_DATM%1PT_CLM51%BGC_SICE_SOCN_SROF_SGLC_SWAV + IHist1PtClm60Bgc + HIST_DATM%1PT_CLM60%BGC_SICE_SOCN_SROF_SGLC_SWAV - IHist1PtClm51Fates - HIST_DATM%1PT_CLM51%FATES_SICE_SOCN_SROF_SGLC_SWAV + IHist1PtClm60Fates + HIST_DATM%1PT_CLM60%FATES_SICE_SOCN_SROF_SGLC_SWAV - I1PtClm51SpRs - 2000_DATM%1PT_CLM51%SP_SICE_SOCN_SROF_SGLC_SWAV + I1PtClm60SpRs + 2000_DATM%1PT_CLM60%SP_SICE_SOCN_SROF_SGLC_SWAV @@ -83,16 +83,20 @@ I2000Clm50SpRs 2000_DATM%GSWP3v1_CLM50%SP_SICE_SOCN_SROF_SGLC_SWAV + + I2000Clm60SpRs + 2000_DATM%GSWP3v1_CLM60%SP_SICE_SOCN_SROF_SGLC_SWAV + - I2000Clm51Sp - 2000_DATM%GSWP3v1_CLM51%SP_SICE_SOCN_MOSART_SGLC_SWAV + I2000Clm60Sp + 2000_DATM%GSWP3v1_CLM60%SP_SICE_SOCN_MOSART_SGLC_SWAV - I2000Clm51SpRs - 2000_DATM%GSWP3v1_CLM51%SP_SICE_SOCN_SROF_SGLC_SWAV + I2000Clm60SpRs + 2000_DATM%GSWP3v1_CLM60%SP_SICE_SOCN_SROF_SGLC_SWAV @@ -128,13 +132,13 @@ - I2000Clm51BgcCrop - 2000_DATM%GSWP3v1_CLM51%BGC-CROP_SICE_SOCN_MOSART_SGLC_SWAV + I2000Clm60BgcCrop + 2000_DATM%GSWP3v1_CLM60%BGC-CROP_SICE_SOCN_MOSART_SGLC_SWAV - I2000Clm51Bgc - 2000_DATM%GSWP3v1_CLM51%BGC_SICE_SOCN_MOSART_SGLC_SWAV + I2000Clm60Bgc + 2000_DATM%GSWP3v1_CLM60%BGC_SICE_SOCN_MOSART_SGLC_SWAV @@ -152,6 +156,11 @@ + + I1850Clm60SpCru + 1850_DATM%CRUv7_CLM60%SP_SICE_SOCN_MOSART_SGLC_SWAV + + I1850Clm50BgcCrop 1850_DATM%GSWP3v1_CLM50%BGC-CROP_SICE_SOCN_MOSART_SGLC_SWAV @@ -160,33 +169,42 @@ - I1850Clm51BgcCrop - 1850_DATM%GSWP3v1_CLM51%BGC-CROP_SICE_SOCN_MOSART_SGLC_SWAV + I1850Clm60BgcCrop + 1850_DATM%GSWP3v1_CLM60%BGC-CROP_SICE_SOCN_MOSART_SGLC_SWAV + + + + + I1850Clm60BgcCrop + 1850_DATM%GSWP3v1_CLM60%BGC-CROP_SICE_SOCN_MOSART_SGLC_SWAV - I1850Clm51Sp - 1850_DATM%GSWP3v1_CLM51%SP_SICE_SOCN_MOSART_SGLC_SWAV + I1850Clm60Sp + 1850_DATM%GSWP3v1_CLM60%SP_SICE_SOCN_MOSART_SGLC_SWAV - I1850Clm51Bgc - 1850_DATM%GSWP3v1_CLM51%BGC_SICE_SOCN_MOSART_SGLC_SWAV + I1850Clm60Bgc + 1850_DATM%GSWP3v1_CLM60%BGC_SICE_SOCN_MOSART_SGLC_SWAV + I1850Clm50BgcCropCmip6 1850_DATM%GSWP3v1_CLM50%BGC-CROP-CMIP6DECK_SICE_SOCN_MOSART_SGLC_SWAV + I1850Clm50BgcCropCmip6waccm 1850_DATM%GSWP3v1_CLM50%BGC-CROP-CMIP6WACCMDECK_SICE_SOCN_MOSART_SGLC_SWAV + I1850Clm50BgcCropCru 1850_DATM%CRUv7_CLM50%BGC-CROP_SICE_SOCN_MOSART_SGLC_SWAV @@ -194,9 +212,19 @@ + + + I1850Clm60BgcCropCru + 1850_DATM%CRUv7_CLM60%BGC-CROP_SICE_SOCN_MOSART_SGLC_SWAV + + + + I2000Clm60BgcCropQianRs + 2000_DATM%QIA_CLM60%BGC-CROP_SICE_SOCN_SROF_SGLC_SWAV + I2000Clm50BgcCropQianRs 2000_DATM%QIA_CLM50%BGC-CROP_SICE_SOCN_SROF_SGLC_SWAV @@ -223,8 +251,8 @@ - I2000Clm51Fates - 2000_DATM%GSWP3v1_CLM51%FATES_SICE_SOCN_MOSART_SGLC_SWAV + I2000Clm60Fates + 2000_DATM%GSWP3v1_CLM60%FATES_SICE_SOCN_MOSART_SGLC_SWAV I2000Clm50Fates @@ -235,12 +263,12 @@ 2000_DATM%CRUv7_CLM50%FATES_SICE_SOCN_SROF_SGLC_SWAV - I2000Clm51FatesSpCruRsGs - 2000_DATM%CRUv7_CLM51%FATES-SP_SICE_SOCN_SROF_SGLC_SWAV + I2000Clm60FatesSpCruRsGs + 2000_DATM%CRUv7_CLM60%FATES-SP_SICE_SOCN_SROF_SGLC_SWAV - I2000Clm51FatesSpRsGs - 2000_DATM%GSWP3v1_CLM51%FATES-SP_SICE_SOCN_SROF_SGLC_SWAV + I2000Clm60FatesSpRsGs + 2000_DATM%GSWP3v1_CLM60%FATES-SP_SICE_SOCN_SROF_SGLC_SWAV I2000Clm50FatesCru @@ -252,8 +280,8 @@ 2000_DATM%GSWP3v1_CLM50%FATES_SICE_SOCN_SROF_SGLC_SWAV - I2000Clm51FatesRs - 2000_DATM%GSWP3v1_CLM51%FATES_SICE_SOCN_SROF_SGLC_SWAV + I2000Clm60FatesRs + 2000_DATM%GSWP3v1_CLM60%FATES_SICE_SOCN_SROF_SGLC_SWAV @@ -261,6 +289,16 @@ 1850_DATM%GSWP3v1_CLM50%BGC_SICE_SOCN_MOSART_SGLC_SWAV + + I1850Clm60BgcNoAnthro + 1850_DATM%GSWP3v1_CLM60%BGC-NOANTHRO_SICE_SOCN_MOSART_SGLC_SWAV + + + + I1850Clm60SpNoAnthro + 1850_DATM%GSWP3v1_CLM60%SP-NOANTHRO_SICE_SOCN_MOSART_SGLC_SWAV + + I1850Clm50BgcNoAnthro 1850_DATM%GSWP3v1_CLM50%BGC-NOANTHRO_SICE_SOCN_MOSART_SGLC_SWAV @@ -271,6 +309,7 @@ 1850_DATM%GSWP3v1_CLM50%SP-NOANTHRO_SICE_SOCN_MOSART_SGLC_SWAV + IHistClm50BgcCrop HIST_DATM%GSWP3v1_CLM50%BGC-CROP_SICE_SOCN_MOSART_SGLC_SWAV @@ -279,23 +318,34 @@ - I1850Clm51SpNoAnthro - 1850_DATM%GSWP3v1_CLM51%SP-NOANTHRO_SICE_SOCN_MOSART_SGLC_SWAV + I1850Clm60SpNoAnthro + 1850_DATM%GSWP3v1_CLM60%SP-NOANTHRO_SICE_SOCN_MOSART_SGLC_SWAV + + IHistClm60Sp + HIST_DATM%GSWP3v1_CLM60%SP_SICE_SOCN_MOSART_SGLC_SWAV + + + IHistClm51Sp HIST_DATM%GSWP3v1_CLM51%SP_SICE_SOCN_MOSART_SGLC_SWAV - IHistClm51Bgc - HIST_DATM%GSWP3v1_CLM51%BGC_SICE_SOCN_MOSART_SGLC_SWAV + IHistClm60SpRs + HIST_DATM%GSWP3v1_CLM60%SP_SICE_SOCN_SROF_SGLC_SWAV - IHistClm51BgcCrop - HIST_DATM%GSWP3v1_CLM51%BGC-CROP_SICE_SOCN_MOSART_SGLC_SWAV + IHistClm60Bgc + HIST_DATM%GSWP3v1_CLM60%BGC_SICE_SOCN_MOSART_SGLC_SWAV + + + + IHistClm60BgcCrop + HIST_DATM%GSWP3v1_CLM60%BGC-CROP_SICE_SOCN_MOSART_SGLC_SWAV @@ -312,6 +362,11 @@ + + IHistClm60SpCru + HIST_DATM%CRUv7_CLM60%SP_SICE_SOCN_MOSART_SGLC_SWAV + + IHistClm50Bgc HIST_DATM%GSWP3v1_CLM50%BGC_SICE_SOCN_MOSART_SGLC_SWAV @@ -330,7 +385,14 @@ HIST_DATM%QIA_CLM50%BGC_SICE_SOCN_SROF_SGLC_SWAV - + + IHistClm60BgcQianRs + HIST_DATM%QIA_CLM60%BGC_SICE_SOCN_SROF_SGLC_SWAV + + + ISSP585Clm50BgcCrop SSP585_DATM%GSWP3v1_CLM50%BGC-CROP_SICE_SOCN_MOSART_SGLC_SWAV @@ -371,14 +433,24 @@ SSP534_DATM%GSWP3v1_CLM50%BGC-CROP_SICE_SOCN_MOSART_SGLC_SWAV + + + ISSP585Clm60BgcCrop + SSP585_DATM%GSWP3v1_CLM60%BGC-CROP_SICE_SOCN_MOSART_SGLC_SWAV + - + + IHistClm50BgcCropQianRs HIST_DATM%QIA_CLM50%BGC-CROP_SICE_SOCN_SROF_SGLC_SWAV + + IHistClm60BgcCropQianRs + HIST_DATM%QIA_CLM60%BGC-CROP_SICE_SOCN_SROF_SGLC_SWAV + @@ -521,7 +593,9 @@ 2000_DATM%CRUv7_CLM45%SP-VIC_SICE_SOCN_RTM_SGLC_SWAV - + I1850Clm50SpG @@ -538,12 +612,6 @@ 1850_DATM%GSWP3v1_CLM50%SP_SICE_SOCN_MOSART_CISM2%AIS-EVOLVE%GRIS-EVOLVE_SWAV - - - I1850Clm50SpRsGag - 1850_DATM%GSWP3v1_CLM50%SP_SICE_SOCN_SROF_CISM2%AIS-EVOLVE%GRIS-EVOLVE_SWAV - - IHistClm50SpG HIST_DATM%GSWP3v1_CLM50%SP_SICE_SOCN_MOSART_CISM2%GRIS-EVOLVE_SWAV @@ -559,13 +627,38 @@ HIST_DATM%GSWP3v1_CLM50%BGC-CROP_SICE_SOCN_MOSART_CISM2%GRIS-EVOLVE_SWAV - + + I1850Clm60BgcCropG + 1850_DATM%GSWP3v1_CLM60%BGC-CROP_SICE_SOCN_MOSART_CISM2%GRIS-EVOLVE_SWAV + + + + I1850Clm51BgcCropG + 1850_DATM%GSWP3v1_CLM51%BGC-CROP_SICE_SOCN_MOSART_CISM2%GRIS-EVOLVE_SWAV + + + + + + I1850Clm50SpRsGag + 1850_DATM%GSWP3v1_CLM50%SP_SICE_SOCN_SROF_CISM2%AIS-EVOLVE%GRIS-EVOLVE_SWAV + + + + I1850Clm60SpRs + 1850_DATM%GSWP3v1_CLM60%SP_SICE_SOCN_SROF_SGLC_SWAV + + + + + both purposes.) +--> I2000Ctsm50NwpSpAsRs 2000_SATM_CLM50%NWP-SP_SICE_SOCN_SROF_SGLC_SWAV diff --git a/cime_config/config_tests.xml b/cime_config/config_tests.xml index 536f79aeec..c0b6afed9d 100644 --- a/cime_config/config_tests.xml +++ b/cime_config/config_tests.xml @@ -15,6 +15,16 @@ This defines various CTSM-specific system tests FALSE + + Build and run the mksurfdata_esmf tool to generate a new fsurdat; then run the CTSM with this fsurdat + 1 + FALSE + FALSE + never + $STOP_OPTION + $STOP_N + + Run the CTSM with an fsurdat generated by the fsurdat_modify tool 1 diff --git a/cime_config/testdefs/ExpectedTestFails.xml b/cime_config/testdefs/ExpectedTestFails.xml index a510f38545..fe6a54c221 100644 --- a/cime_config/testdefs/ExpectedTestFails.xml +++ b/cime_config/testdefs/ExpectedTestFails.xml @@ -28,9 +28,29 @@ --> - + + + + PEND + #2460 + + + + + + FAIL + CDEPS/#243 + + + + + FAIL + #2444 + + + FAIL @@ -38,21 +58,21 @@ - + FAIL #1733 - + FAIL #1733 - + FAIL #2310 @@ -63,7 +83,7 @@ - + FAIL #2310 @@ -74,7 +94,7 @@ - + FAIL #2310 @@ -85,7 +105,7 @@ - + FAIL #2310 @@ -96,7 +116,7 @@ - + FAIL #2310 @@ -114,6 +134,13 @@ + + + FAIL + #2373 + + + FAIL @@ -127,11 +154,32 @@ #2454 - - + + + + FAIL + #2310 + + + FAIL + #2310 + + + + + + FAIL + #2310 + + + FAIL + #2310 + + + - + FAIL #2321 @@ -139,6 +187,10 @@ + + FAIL + #2373 + FAIL FATES#701 @@ -152,24 +204,24 @@ - - + + FAIL - FATES#701 + #2373 - - - PEND - #1045 + + + FAIL + FATES#701 - - - PEND - #1045 + + + FAIL + #2261 @@ -216,4 +268,31 @@ + + + FAIL + #2478 + + + + + + FAIL + #2310 + + + FAIL + #2310 + + + + + + + + FAIL + MOSART#91 + + + diff --git a/cime_config/testdefs/testlist_clm.xml b/cime_config/testdefs/testlist_clm.xml index 2b8048a64d..05526b3529 100644 --- a/cime_config/testdefs/testlist_clm.xml +++ b/cime_config/testdefs/testlist_clm.xml @@ -1,12 +1,24 @@ + - + - + - + @@ -21,26 +33,6 @@ - - - - - - - - - - - - - - - - - - - - @@ -81,9 +73,8 @@ - + - @@ -91,7 +82,7 @@ - + @@ -100,36 +91,46 @@ - + + - + + + + + + + + + + + - + - + - + - + - + - @@ -137,44 +138,116 @@ - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + - + - - + + + + + + + + + + + @@ -184,7 +257,7 @@ - + @@ -202,29 +275,27 @@ + - - + - - + - @@ -234,7 +305,6 @@ - @@ -242,6 +312,25 @@ + + + + + + + + + + + + + + + + + + + @@ -263,7 +352,7 @@ - + @@ -279,7 +368,7 @@ - + @@ -288,9 +377,8 @@ - + - @@ -298,15 +386,6 @@ - - - - - - - - - @@ -395,17 +474,16 @@ - + - - + - + @@ -414,25 +492,25 @@ - + - + - + - + - + @@ -471,43 +549,161 @@ + - - + - - + + + + + + + + + + + + + + + + + + + + - + - + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -519,22 +715,39 @@ - - + - - + + + + + + + + + + + + + + + + + + + + @@ -577,14 +790,14 @@ - + - + @@ -600,7 +813,6 @@ - @@ -627,19 +839,29 @@ - + - + + + + + + + + + + + + - @@ -649,7 +871,6 @@ - @@ -657,7 +878,7 @@ - + @@ -665,7 +886,7 @@ - + @@ -674,7 +895,7 @@ - + @@ -683,7 +904,7 @@ - + @@ -692,7 +913,7 @@ - + @@ -749,7 +970,7 @@ - + @@ -757,7 +978,7 @@ - + @@ -765,7 +986,7 @@ - + @@ -774,7 +995,7 @@ - + @@ -783,7 +1004,7 @@ - + @@ -885,7 +1106,7 @@ - + @@ -894,7 +1115,7 @@ - + @@ -933,7 +1154,7 @@ - + @@ -964,7 +1185,6 @@ - @@ -990,7 +1210,6 @@ - @@ -1000,7 +1219,6 @@ - @@ -1050,26 +1268,6 @@ - - - - - - - - - - - - - - - - - - - - @@ -1091,6 +1289,7 @@ + @@ -1150,46 +1349,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1199,27 +1358,7 @@ - - - - - - - - - - - - - - - - - - - - - + @@ -1229,7 +1368,7 @@ - + @@ -1307,13 +1446,14 @@ + - + @@ -1322,7 +1462,7 @@ - + @@ -1452,14 +1592,13 @@ - + - - + @@ -1582,7 +1721,7 @@ - + @@ -1591,7 +1730,7 @@ - + @@ -1665,7 +1804,7 @@ - + @@ -1674,7 +1813,7 @@ - + @@ -1701,17 +1840,17 @@ - + - + - + @@ -1720,17 +1859,17 @@ - + - + - + @@ -1743,8 +1882,9 @@ - + + @@ -1781,7 +1921,7 @@ - + @@ -1791,7 +1931,7 @@ - + @@ -1825,7 +1965,7 @@ - + @@ -1865,7 +2005,7 @@ - + @@ -1888,27 +2028,24 @@ - - + - - - + - @@ -1916,9 +2053,8 @@ - + - @@ -1926,9 +2062,8 @@ - + - @@ -1936,24 +2071,42 @@ + - - + - - + + + + + + + + + + + + + + + + + + + + @@ -1996,13 +2149,9 @@ - + - - - - - + @@ -2127,10 +2276,9 @@ - + - - + @@ -2140,7 +2288,7 @@ - + @@ -2151,7 +2299,7 @@ - + @@ -2162,7 +2310,7 @@ - + @@ -2174,7 +2322,7 @@ - + @@ -2185,7 +2333,7 @@ - + @@ -2197,7 +2345,7 @@ - + @@ -2210,7 +2358,7 @@ - + @@ -2223,17 +2371,6 @@ - - - - - - - - - - - @@ -2294,7 +2431,6 @@ - @@ -2348,7 +2484,7 @@ - + @@ -2356,46 +2492,50 @@ - + - - - - + - + - + - + - - + - + - + + + + + + + + + + - - + @@ -2408,7 +2548,7 @@ - + @@ -2438,6 +2578,15 @@ + + + + + + + + + @@ -2447,7 +2596,7 @@ - + @@ -2457,7 +2606,7 @@ - + @@ -2488,21 +2637,21 @@ - - + - + + @@ -2625,7 +2774,7 @@ - + @@ -2634,7 +2783,7 @@ - + @@ -2747,7 +2896,7 @@ - + @@ -2757,7 +2906,7 @@ - + @@ -2846,6 +2995,7 @@ + @@ -3101,9 +3251,10 @@ - + + @@ -3111,7 +3262,7 @@ - + @@ -3121,7 +3272,7 @@ - + @@ -3132,7 +3283,7 @@ - + @@ -3142,7 +3293,7 @@ - + @@ -3152,7 +3303,7 @@ - + @@ -3163,7 +3314,7 @@ - + @@ -3173,7 +3324,7 @@ - + @@ -3253,7 +3404,6 @@ - @@ -3272,10 +3422,11 @@ - + + @@ -3284,16 +3435,26 @@ - + + + + + + + + + + + @@ -3307,6 +3468,29 @@ + + + + + + + + + + + + + + + + + + + + + + + @@ -3444,7 +3628,6 @@ - @@ -3453,7 +3636,7 @@ - + @@ -3463,7 +3646,7 @@ - + @@ -3472,7 +3655,7 @@ - + @@ -3482,7 +3665,7 @@ - + diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdLandUse/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/FatesColdLandUse/user_nl_clm index 098d4fd33a..668f9c861d 100644 --- a/cime_config/testdefs/testmods_dirs/clm/FatesColdLandUse/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdLandUse/user_nl_clm @@ -1,2 +1,2 @@ -flanduse_timeseries = '$DIN_LOC_ROOT/lnd/clm2/surfdata_map/landuse.timeseries_4x5_hist_simyr1850-2015_200311.nc' +flanduse_timeseries = '$DIN_LOC_ROOT/lnd/clm2/surfdata_esmf/ctsm5.2.0/landuse.timeseries_4x5_hist_16_CMIP6_1850-2015_c230620.nc' do_harvest = .true. diff --git a/cime_config/testdefs/testmods_dirs/clm/Hillslope/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/Hillslope/user_nl_clm index afdcf4d1fc..4fc6fc2373 100644 --- a/cime_config/testdefs/testmods_dirs/clm/Hillslope/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/Hillslope/user_nl_clm @@ -6,6 +6,6 @@ hillslope_transmissivity_method = 'LayerSum' hillslope_pft_distribution_method = 'PftLowlandUpland' hillslope_soil_profile_method = 'Uniform' -fsurdat = '$DIN_LOC_ROOT/lnd/clm2/testdata/surfdata_10x15_78pfts_simyr2000_synthetic_cosphill_1.3.nc' +fsurdat = '$DIN_LOC_ROOT/lnd/clm2/testdata/surfdata_10x15_hist_2000_78pfts_c240216.synthetic_hillslopes.nc' use_ssre = .false. diff --git a/cime_config/testdefs/testmods_dirs/clm/USUMB_mct/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/USUMB_mct/include_user_mods deleted file mode 100644 index 3e31b09d16..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/USUMB_mct/include_user_mods +++ /dev/null @@ -1 +0,0 @@ -../CLM1PTStartDate diff --git a/cime_config/testdefs/testmods_dirs/clm/USUMB_mct/shell_commands b/cime_config/testdefs/testmods_dirs/clm/USUMB_mct/shell_commands deleted file mode 100755 index e410197c3d..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/USUMB_mct/shell_commands +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash -# shell commands to execute xmlchange commands written by PTCLMmkdata: which is now unsupported -./xmlchange CLM_USRDAT_NAME=1x1pt_US-UMB -./xmlchange DATM_CLMNCEP_YR_START=1999 -./xmlchange DATM_CLMNCEP_YR_END=2006 -# Comment this out if NINST_LND is greater than 1 (see: http://bugs.cgd.ucar.edu/show_bug.cgi?id=2521) -./xmlchange MPILIB=mpi-serial -./xmlchange ATM_DOMAIN_PATH='$DIN_LOC_ROOT/lnd/clm2/PTCLMmydatafiles.c171024/1x1pt_US-UMB' -./xmlchange LND_DOMAIN_PATH='$DIN_LOC_ROOT/lnd/clm2/PTCLMmydatafiles.c171024/1x1pt_US-UMB' -./xmlchange ATM_DOMAIN_FILE=domain.lnd.1x1pt_US-UMB_navy.171024.nc -./xmlchange LND_DOMAIN_FILE=domain.lnd.1x1pt_US-UMB_navy.171024.nc -./xmlchange --append CLM_BLDNML_OPTS='-mask navy -no-crop' -./xmlchange CALENDAR=GREGORIAN -./xmlchange DOUT_S=FALSE -./xmlchange ATM_NCPL=24 -./xmlchange RUN_STARTDATE=1999-01-01 -./xmlchange DATM_CLMNCEP_YR_ALIGN=1999 -./xmlchange DIN_LOC_ROOT_CLMFORC='$DIN_LOC_ROOT/lnd/clm2/PTCLMmydatafiles.c171024' diff --git a/cime_config/testdefs/testmods_dirs/clm/USUMB_mct/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/USUMB_mct/user_nl_clm deleted file mode 100644 index 8bb7848d49..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/USUMB_mct/user_nl_clm +++ /dev/null @@ -1,4 +0,0 @@ -! user_nl_clm namelist options written by PTCLMmkdata, which is no longer available - fsurdat = '$DIN_LOC_ROOT/lnd/clm2/PTCLMmydatafiles.c171024/1x1pt_US-UMB/surfdata_1x1pt_US-UMB_16pfts_Irrig_CMIP6_simyr2000_c171024.nc' - hist_nhtfrq = 0 - hist_mfilt = 1200 diff --git a/cime_config/testdefs/testmods_dirs/clm/USUMB_nuopc/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/USUMB_nuopc/include_user_mods deleted file mode 100644 index 3e31b09d16..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/USUMB_nuopc/include_user_mods +++ /dev/null @@ -1 +0,0 @@ -../CLM1PTStartDate diff --git a/cime_config/testdefs/testmods_dirs/clm/USUMB_nuopc/shell_commands b/cime_config/testdefs/testmods_dirs/clm/USUMB_nuopc/shell_commands deleted file mode 100755 index 43fe16a192..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/USUMB_nuopc/shell_commands +++ /dev/null @@ -1,15 +0,0 @@ -# shell commands to execute xmlchange commands written by PTCLMmkdata: which is now unsupported -./xmlchange CLM_USRDAT_NAME=1x1pt_US-UMB -./xmlchange DATM_YR_START=1999 -./xmlchange DATM_YR_END=2006 -# Comment this out if NINST_LND is greater than 1 (see: http://bugs.cgd.ucar.edu/show_bug.cgi?id=2521) -./xmlchange MPILIB=mpi-serial -./xmlchange --append CLM_BLDNML_OPTS='-mask navy -no-crop' -./xmlchange CALENDAR=GREGORIAN -./xmlchange DOUT_S=FALSE -./xmlchange ATM_NCPL=24 -./xmlchange RUN_STARTDATE=1999-01-01 -./xmlchange DATM_YR_ALIGN=1999 -./xmlchange DIN_LOC_ROOT_CLMFORC='$DIN_LOC_ROOT/lnd/clm2/PTCLMmydatafiles.c171024' -./xmlchange PTS_LON=275.2862 -./xmlchange PTS_LAT=45.5598 diff --git a/cime_config/testdefs/testmods_dirs/clm/USUMB_nuopc/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/USUMB_nuopc/user_nl_clm deleted file mode 100644 index 8bb7848d49..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/USUMB_nuopc/user_nl_clm +++ /dev/null @@ -1,4 +0,0 @@ -! user_nl_clm namelist options written by PTCLMmkdata, which is no longer available - fsurdat = '$DIN_LOC_ROOT/lnd/clm2/PTCLMmydatafiles.c171024/1x1pt_US-UMB/surfdata_1x1pt_US-UMB_16pfts_Irrig_CMIP6_simyr2000_c171024.nc' - hist_nhtfrq = 0 - hist_mfilt = 1200 diff --git a/cime_config/testdefs/testmods_dirs/clm/clm51cam6LndTuningModeCiso/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/clm51cam6LndTuningModeCiso/include_user_mods deleted file mode 100644 index aa76c52034..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/clm51cam6LndTuningModeCiso/include_user_mods +++ /dev/null @@ -1 +0,0 @@ -../clm51cam6LndTuningMode diff --git a/cime_config/testdefs/testmods_dirs/clm/clm60cam6LndTuningMode/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/clm60cam6LndTuningMode/include_user_mods new file mode 100644 index 0000000000..fe0e18cf88 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/clm60cam6LndTuningMode/include_user_mods @@ -0,0 +1 @@ +../default diff --git a/cime_config/testdefs/testmods_dirs/clm/clm60cam6LndTuningMode/shell_commands b/cime_config/testdefs/testmods_dirs/clm/clm60cam6LndTuningMode/shell_commands new file mode 100644 index 0000000000..e81a241e64 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/clm60cam6LndTuningMode/shell_commands @@ -0,0 +1,5 @@ +#!/bin/bash + +./xmlchange LND_TUNING_MODE="clm6_0_cam6.0" +./xmlchange ROF_NCPL='$ATM_NCPL' + diff --git a/cime_config/testdefs/testmods_dirs/clm/clm60cam6LndTuningModeCiso/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/clm60cam6LndTuningModeCiso/include_user_mods new file mode 100644 index 0000000000..3dabdc9aeb --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/clm60cam6LndTuningModeCiso/include_user_mods @@ -0,0 +1 @@ +../clm60cam6LndTuningMode diff --git a/cime_config/testdefs/testmods_dirs/clm/clm51cam6LndTuningModeCiso/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/clm60cam6LndTuningModeCiso/user_nl_clm similarity index 100% rename from cime_config/testdefs/testmods_dirs/clm/clm51cam6LndTuningModeCiso/user_nl_clm rename to cime_config/testdefs/testmods_dirs/clm/clm60cam6LndTuningModeCiso/user_nl_clm diff --git a/cime_config/testdefs/testmods_dirs/clm/clm60cam6LndTuningModeZDustSoilErod/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/clm60cam6LndTuningModeZDustSoilErod/include_user_mods new file mode 100644 index 0000000000..3dabdc9aeb --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/clm60cam6LndTuningModeZDustSoilErod/include_user_mods @@ -0,0 +1 @@ +../clm60cam6LndTuningMode diff --git a/cime_config/testdefs/testmods_dirs/clm/clm60cam6LndTuningModeZDustSoilErod/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/clm60cam6LndTuningModeZDustSoilErod/user_nl_clm new file mode 100644 index 0000000000..93b7ee2e48 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/clm60cam6LndTuningModeZDustSoilErod/user_nl_clm @@ -0,0 +1,3 @@ +! Turn on using the soil eroditability file in CTSM +dust_emis_method = 'Zender_2003' +zender_soil_erod_source = 'lnd' diff --git a/cime_config/testdefs/testmods_dirs/clm/clm60cam6LndTuningMode_1979Start/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/clm60cam6LndTuningMode_1979Start/include_user_mods new file mode 100644 index 0000000000..3dabdc9aeb --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/clm60cam6LndTuningMode_1979Start/include_user_mods @@ -0,0 +1 @@ +../clm60cam6LndTuningMode diff --git a/cime_config/testdefs/testmods_dirs/clm/clm60cam6LndTuningMode_1979Start/shell_commands b/cime_config/testdefs/testmods_dirs/clm/clm60cam6LndTuningMode_1979Start/shell_commands new file mode 100644 index 0000000000..2aafcc1186 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/clm60cam6LndTuningMode_1979Start/shell_commands @@ -0,0 +1 @@ +./xmlchange RUN_STARTDATE=1979-01-01 diff --git a/cime_config/testdefs/testmods_dirs/clm/clm60cam6LndTuningMode_2013Start/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/clm60cam6LndTuningMode_2013Start/include_user_mods new file mode 100644 index 0000000000..3dabdc9aeb --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/clm60cam6LndTuningMode_2013Start/include_user_mods @@ -0,0 +1 @@ +../clm60cam6LndTuningMode diff --git a/cime_config/testdefs/testmods_dirs/clm/clm60cam6LndTuningMode_2013Start/shell_commands b/cime_config/testdefs/testmods_dirs/clm/clm60cam6LndTuningMode_2013Start/shell_commands new file mode 100644 index 0000000000..035842f982 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/clm60cam6LndTuningMode_2013Start/shell_commands @@ -0,0 +1 @@ +./xmlchange RUN_STARTDATE=2013-01-01 diff --git a/cime_config/testdefs/testmods_dirs/clm/collapse_pfts_78_to_16_decStart_f10/README b/cime_config/testdefs/testmods_dirs/clm/collapse_pfts_78_to_16_decStart_f10/README index af5d819ffc..dbd0696317 100644 --- a/cime_config/testdefs/testmods_dirs/clm/collapse_pfts_78_to_16_decStart_f10/README +++ b/cime_config/testdefs/testmods_dirs/clm/collapse_pfts_78_to_16_decStart_f10/README @@ -5,19 +5,20 @@ exercising the collapse2gencrop branch ability to collapse the full crop data to clm's generic crops. According to the file -/glade/work/slevis/git/collapse_pfts/bld/namelist_files/namelist_defaults_clm4_5.xml +bld/namelist_files/namelist_defaults_ctsm.xml the following two files used in this test are default files for the following options: -fsurdat = '$DIN_LOC_ROOT/lnd/clm2/surfdata_map/surfdata_10x15_78pfts_CMIP6_simyr1850_c170824.nc' +fsurdat = '$DIN_LOC_ROOT/lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_10x15_hist_1850_78pfts_c240216.nc' +hgrid="10x15" sim_year="1850" use_crop=".false." irrigate=".true." hgrid="10x15" sim_year="1850" use_crop=".true." -flanduse_timeseries = '$DIN_LOC_ROOT/lnd/clm2/surfdata_map/landuse.timeseries_10x15_hist_78pfts_CMIP6_simyr1850-2015_c170824.nc' -hgrid="10x15" sim_year_range="1850-2000" use_crop=".true." -hgrid="10x15" rcp="8.5" sim_year_range="1850-2100" use_crop=".true." -hgrid="10x15" rcp="6" sim_year_range="1850-2100" use_crop=".true." -hgrid="10x15" rcp="4.5" sim_year_range="1850-2100" use_crop=".true." -hgrid="10x15" rcp="2.6" sim_year_range="1850-2100" use_crop=".true." +flanduse_timeseries = '$DIN_LOC_ROOT/lnd/clm2/surfdata_esmf/ctsm5.2.0/landuse.timeseries_10x15_SSP2-4.5_1850-2100_78pfts_c240216.nc' +-hgrid="10x15" sim_year_range="1850-2000" use_crop=".true." +-hgrid="10x15" rcp="8.5" sim_year_range="1850-2100" use_crop=".true." +-hgrid="10x15" rcp="6" sim_year_range="1850-2100" use_crop=".true." +-hgrid="10x15" rcp="4.5" sim_year_range="1850-2100" use_crop=".true." +-hgrid="10x15" rcp="2.6" sim_year_range="1850-2100" use_crop=".true." This test includes the settings of the decStart test so as to also test the end-of-year transition since it's an IHist case and transient vegetation gets diff --git a/cime_config/testdefs/testmods_dirs/clm/collapse_pfts_78_to_16_decStart_f10/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/collapse_pfts_78_to_16_decStart_f10/user_nl_clm index 8c4fed6873..d7be01280b 100644 --- a/cime_config/testdefs/testmods_dirs/clm/collapse_pfts_78_to_16_decStart_f10/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/collapse_pfts_78_to_16_decStart_f10/user_nl_clm @@ -1,2 +1,2 @@ -fsurdat = '$DIN_LOC_ROOT/lnd/clm2/surfdata_map/surfdata_10x15_78pfts_CMIP6_simyr1850_c170824.nc' -flanduse_timeseries = '$DIN_LOC_ROOT/lnd/clm2/surfdata_map/landuse.timeseries_10x15_hist_78pfts_CMIP6_simyr1850-2015_c170824.nc' +fsurdat = '$DIN_LOC_ROOT/lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_10x15_hist_1850_78pfts_c240216.nc' +flanduse_timeseries = '$DIN_LOC_ROOT/lnd/clm2/surfdata_esmf/ctsm5.2.0/landuse.timeseries_10x15_SSP2-4.5_1850-2100_78pfts_c240216.nc' diff --git a/cime_config/testdefs/testmods_dirs/clm/cropMonthOutput/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/cropMonthOutput/user_nl_clm index ae4284da6b..8f779ed011 100644 --- a/cime_config/testdefs/testmods_dirs/clm/cropMonthOutput/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/cropMonthOutput/user_nl_clm @@ -1,2 +1,7 @@ hist_nhtfrq = 0,-240,17520 hist_mfilt = 1,1,1 + +! NOTE slevis (2024/2/23) Adding option for tests to pass. In the long term +! ensure that subset_data generates fsurdat and landuse files consistent with +! each other. +check_dynpft_consistency = .false. diff --git a/cime_config/testdefs/testmods_dirs/clm/decStart1851_noinitial/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/decStart1851_noinitial/user_nl_clm new file mode 100644 index 0000000000..78c8d17566 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/decStart1851_noinitial/user_nl_clm @@ -0,0 +1,4 @@ +! NOTE slevis (2024/2/23) Adding option for tests to pass. In the long term +! ensure that subset_data generates fsurdat and landuse files consistent with +! each other. +check_dynpft_consistency = .false. diff --git a/cime_config/testdefs/testmods_dirs/clm/f09_dec1990Start_GU_LULCC/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/f09_dec1990Start_GU_LULCC/user_nl_clm index efb3212d5f..0dbc0b4942 100644 --- a/cime_config/testdefs/testmods_dirs/clm/f09_dec1990Start_GU_LULCC/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/f09_dec1990Start_GU_LULCC/user_nl_clm @@ -1,5 +1,5 @@ ! Specify a dataset that has non-zero Gross Unrepresented Land Use change fields on it ! And turn it on - flanduse_timeseries = '$DIN_LOC_ROOT/lnd/clm2/surfdata_map/ctsm5.1.dev052/landuse.timeseries_0.9x1.25_hist_78pfts_CMIP6_simyr1700-2021_c220825.nc' - fsurdat = '$DIN_LOC_ROOT/lnd/clm2/surfdata_map/ctsm5.1.dev052/surfdata_0.9x1.25_hist_78pfts_CMIP6_simyr1700_c220825.nc' + flanduse_timeseries = '$DIN_LOC_ROOT/lnd/clm2/surfdata_esmf/ctsm5.2.0/landuse.timeseries_0.9x1.25_SSP2-4.5_1850-2100_78pfts_c240216.nc' + fsurdat = '$DIN_LOC_ROOT/lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_0.9x1.25_hist_1850_78pfts_c240216.nc' do_grossunrep = .true. diff --git a/cime_config/testdefs/testmods_dirs/clm/mimicsFatesCold/README b/cime_config/testdefs/testmods_dirs/clm/mimicsFatesCold/README new file mode 100644 index 0000000000..38bd37e383 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/mimicsFatesCold/README @@ -0,0 +1,4 @@ +2023/6/22 slevis added: +./xmlchange CLM_BLDNML_OPTS="-ignore_warnings" --append +to get past this error in test: +DON'T use the '-fire_emis' option when '-bgc fates' is activated diff --git a/cime_config/testdefs/testmods_dirs/clm/mimicsFatesCold/shell_commands b/cime_config/testdefs/testmods_dirs/clm/mimicsFatesCold/shell_commands index 2a9f09bd75..08024be91e 100644 --- a/cime_config/testdefs/testmods_dirs/clm/mimicsFatesCold/shell_commands +++ b/cime_config/testdefs/testmods_dirs/clm/mimicsFatesCold/shell_commands @@ -1 +1,2 @@ ./xmlchange CLM_FORCE_COLDSTART="on" +./xmlchange CLM_BLDNML_OPTS="-ignore_warnings" --append diff --git a/cime_config/testdefs/testmods_dirs/clm/smallville_dynlakes_monthly/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/smallville_dynlakes_monthly/user_nl_clm index 923abcdaec..c86418dabd 100644 --- a/cime_config/testdefs/testmods_dirs/clm/smallville_dynlakes_monthly/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/smallville_dynlakes_monthly/user_nl_clm @@ -1,8 +1,14 @@ do_transient_lakes = .true. -! This file was created with the following command: -! ncap2 -s 'PCT_LAKE=array(0.0,0.0,PCT_CROP); PCT_LAKE={0.,50.,25.,25.,25.,25.}; HASLAKE=array(1.,1.,AREA); PCT_CROP=array(0.0,0.0,PCT_LAKE); PCT_CROP={0.,25.,12.,12.,12.,12.}' landuse.timeseries_1x1_smallvilleIA_hist_78pfts_simyr1850-1855_c160127.nc landuse.timeseries_1x1_smallvilleIA_hist_78pfts_simyr1850-1855_dynLakes_c200928.nc +! The fsurdat and flanduse_timeseries files were created with the following script: +! tools/modify_input_files/modify_smallville.sh + ! Key points are that lake area starts as 0, increases after the first year, then decreases after the second year. ! PCT_CROP is also changed so that PCT_LAKE + PCT_CROP <= 100. (Here, PCT_CROP increases and decreases at the same time as PCT_LAKE in order to exercise the simultaneous increase or decrease of two landunits, but that isn't a critical part of this test.) ! Note that the use of this file means that this testmod can only be used with the 1x1_smallvilleIA grid. -flanduse_timeseries = '$DIN_LOC_ROOT/lnd/clm2/surfdata_map/landuse.timeseries_1x1_smallvilleIA_hist_78pfts_simyr1850-1855_dynLakes_c200928.nc' +flanduse_timeseries = '$DIN_LOC_ROOT/lnd/clm2/surfdata_esmf/ctsm5.2.0/landuse.timeseries_1x1_smallvilleIA_SSP2-4.5_1850-1855_78pfts_dynLakes_c240221.nc' + +! NOTE slevis (2024/2/23) Adding option for tests to pass. In the long term +! ensure that subset_data generates fsurdat and landuse files consistent with +! each other. +check_dynpft_consistency = .false. diff --git a/cime_config/testdefs/testmods_dirs/clm/smallville_dynurban_monthly/modify_smallville_with_dynurban.ncl b/cime_config/testdefs/testmods_dirs/clm/smallville_dynurban_monthly/modify_smallville_with_dynurban.ncl deleted file mode 100644 index 5ac651b508..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/smallville_dynurban_monthly/modify_smallville_with_dynurban.ncl +++ /dev/null @@ -1,72 +0,0 @@ -; NCL script -; modify_smallville_with_dynurban.ncl -; Keith Oleson, Dec 2021 -; Feb 23, 2022: Change HASURBAN to PCT_URBAN_MAX. The output file date has been updated from -; c211206 to c220223. -; Purpose is to create a transient landuse file for the smallville grid for dynamic urban testing -; ERS_Lm25.1x1_smallvilleIA.IHistClm50BgcCropQianRs.cheyenne_gnu.clm-smallville_dynurban_monthly -;************************************** - -load "$NCARG_ROOT/lib/ncarg/nclscripts/csm/gsn_code.ncl" -load "$NCARG_ROOT/lib/ncarg/nclscripts/csm/gsn_csm.ncl" -load "$NCARG_ROOT/lib/ncarg/nclscripts/csm/contributed.ncl" -load "$NCARG_ROOT/lib/ncarg/nclscripts/csm/shea_util.ncl" - -begin - - print ("=========================================") - print ("Start Time: "+systemfunc("date") ) - print ("=========================================") - - infile = "/glade/campaign/cgd/tss/people/oleson/modify_surfdata/landuse.timeseries_1x1_smallvilleIA_hist_78pfts_simyr1850-1855_c160127.nc" - outfile = "/glade/campaign/cgd/tss/people/oleson/modify_surfdata/landuse.timeseries_1x1_smallvilleIA_hist_78pfts_simyr1850-1855_dynUrban_c220223.nc" - - system("cp " + infile + " " + outfile) - - outf = addfile(outfile,"w") - - numurbl = 3 - - pct_crop = outf->PCT_CROP - printVarSummary(pct_crop) - pct_urban = new((/dimsizes(pct_crop(:,0,0)),numurbl,dimsizes(pct_crop(0,:,0)),dimsizes(pct_crop(0,0,:))/),double,"No_FillValue") - pct_urban!0 = "time" - pct_urban&time = pct_crop&time - pct_urban!1 = "numurbl" - pct_urban!2 = pct_crop!1 - pct_urban!3 = pct_crop!2 - pct_urban@long_name = "percent urban for each density type (tbd, hd, md)" - pct_urban@units = "unitless" - printVarSummary(pct_urban) - - pct_urban(:,0,0,0) = (/0.d,20.d,10.d,10.d,10.d,10.d/) - pct_urban(:,1,0,0) = (/0.d,15.d, 8.d, 8.d, 8.d, 8.d/) -;pct_urban(:,2,0,0) = (/0.d,10.d, 5.d, 5.d, 5.d, 5.d/) - pct_urban(:,2,0,0) = (/0.d, 0.d, 0.d, 0.d, 0.d, 0.d/) - - pct_urban_max = new((/numurbl,dimsizes(pct_crop(0,:,0)),dimsizes(pct_crop(0,0,:))/),double,"No_FillValue") - pct_urban_max!0 = pct_urban!1 - pct_urban_max!1 = pct_urban!2 - pct_urban_max!2 = pct_urban!3 - pct_urban_max(0,:,:) = max(pct_urban(:,0,0,0)) - pct_urban_max(1,:,:) = max(pct_urban(:,1,0,0)) - pct_urban_max(2,:,:) = max(pct_urban(:,2,0,0)) - printVarSummary(pct_urban_max) - pct_urban_max@units = "unitless" - pct_urban_max@long_name = "maximum percent urban for each density type (tbd, hd, md)" - - pct_crop(:,0,0) = (/0.,25.,12.,12.,12.,12./) - - outf->PCT_URBAN_MAX = pct_urban_max - outf->PCT_URBAN = pct_urban - outf->PCT_CROP = pct_crop - - outf@history = "This file was created with the following NCL script: -/glade/campaign/cgd/tss/people/oleson/modify_surfdata/modify_smallville_with_dynurban.ncl. The file used as a template is: -/glade/campaign/cesm/cesmdata/inputdata/lnd/clm2/surfdata_map/landuse.timeseries_1x1_smallvilleIA_hist_78pfts_simyr1850-1855_c160127.nc. Key points are that urban area starts as 0, increases after the first year, then decreases after the second year. Medium density urban is set to zero to test the memory-saving behavior of PCT_URBAN_MAX. PCT_CROP is also changed so that PCT_URBAN + PCT_CROP <= 100. (Here, PCT_CROP increases and decreases at the same time as PCT_URBAN in order to exercise the simultaneous increase or decrease of two landunits, but that isn't a critical part of this test.). Note that the use of this file means that this testmod can only be used with the 1x1_smallvilleIA grid." - - print ("=========================================") - print ("Finish Time: "+systemfunc("date") ) - print ("=========================================") - -end diff --git a/cime_config/testdefs/testmods_dirs/clm/smallville_dynurban_monthly/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/smallville_dynurban_monthly/user_nl_clm index 0ba93b1ee2..a5bdb76ac3 100644 --- a/cime_config/testdefs/testmods_dirs/clm/smallville_dynurban_monthly/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/smallville_dynurban_monthly/user_nl_clm @@ -1,13 +1,15 @@ do_transient_urban = .true. -! The flanduse_timeseries file was created with the following NCL script (a copy of this script is in cime_config/testdefs/testmods_dirs/clm/smallville_dynurban_monthly): -! /glade/campaign/cgd/tss/people/oleson/modify_surfdata/modify_smallville_with_dynurban.ncl -! The file used as a template is: -! /glade/campaign/cgd/tss/people/oleson/modify_surfdata/lnd/clm2/surfdata_map/landuse.timeseries_1x1_smallvilleIA_hist_78pfts_simyr1850-1855_c160127.nc +! The fsurdat and flanduse_timeseries files were created with the following script: +! tools/modify_input_files/modify_smallville.sh + ! Key points are that urban area starts as 0, increases after the first year, then decreases after the second year. ! Medium density urban is set to zero to test the memory-saving behavior of PCT_URBAN_MAX. ! PCT_CROP is also changed so that PCT_URBAN + PCT_CROP <= 100. (Here, PCT_CROP increases and decreases at the same time as PCT_URBAN in order to exercise the simultaneous increase or decrease of two landunits, but that isn't a critical part of this test.) ! Note that the use of this file means that this testmod can only be used with the 1x1_smallvilleIA grid. -! Feb 23, 2022: Use updated file with HASURBAN replaced by PCT_URBAN_MAX -!flanduse_timeseries = '$DIN_LOC_ROOT/lnd/clm2/surfdata_map/landuse.timeseries_1x1_smallvilleIA_hist_78pfts_simyr1850-1855_dynUrban_c220223.nc' -flanduse_timeseries = '$DIN_LOC_ROOT/lnd/clm2/surfdata_map/landuse.timeseries_1x1_smallvilleIA_hist_78pfts_simyr1850-1855_dynUrban_c220223.nc' +flanduse_timeseries = '$DIN_LOC_ROOT/lnd/clm2/surfdata_esmf/ctsm5.2.0/landuse.timeseries_1x1_smallvilleIA_SSP2-4.5_1850-1855_78pfts_dynUrban_c240221.nc' + +! NOTE slevis (2024/2/23) Adding option for tests to pass. In the long term +! ensure that subset_data generates fsurdat and landuse files consistent with +! each other. +check_dynpft_consistency = .false. diff --git a/cime_config/usermods_dirs/NEON/FATES/defaults/user_nl_clm b/cime_config/usermods_dirs/NEON/FATES/defaults/user_nl_clm index 2a6b4d76d5..1a9847a69b 100644 --- a/cime_config/usermods_dirs/NEON/FATES/defaults/user_nl_clm +++ b/cime_config/usermods_dirs/NEON/FATES/defaults/user_nl_clm @@ -19,7 +19,7 @@ !---------------------------------------------------------------------------------- flanduse_timeseries = ' ' ! This isn't needed for a non transient case, but will be once we start using transient compsets -fsurdat = "$DIN_LOC_ROOT/lnd/clm2/surfdata_map/NEON/16PFT_mixed/surfdata_1x1_NEON_${NEONSITE}_hist_16pfts_Irrig_CMIP6_simyr2000_c230120.nc" +fsurdat = "$DIN_LOC_ROOT/lnd/clm2/surfdata_esmf/NEON/16PFT_mixed/surfdata_1x1_NEON_${NEONSITE}_hist_2000_16pfts_c240206.nc" ! h1 output stream hist_fincl2 = 'FATES_AUTORESP','FCEV','FCTR','FGEV','FIRA','FSA','FSH','FATES_GPP','FATES_GPP_PF','H2OSOI', diff --git a/cime_config/usermods_dirs/NEON/defaults/user_nl_clm b/cime_config/usermods_dirs/NEON/defaults/user_nl_clm index 419ff0314c..b73da1f33e 100644 --- a/cime_config/usermods_dirs/NEON/defaults/user_nl_clm +++ b/cime_config/usermods_dirs/NEON/defaults/user_nl_clm @@ -19,7 +19,7 @@ !---------------------------------------------------------------------------------- flanduse_timeseries = ' ' ! This isn't needed for a non transient case, but will be once we start using transient compsets -fsurdat = "$DIN_LOC_ROOT/lnd/clm2/surfdata_map/NEON/surfdata_1x1_NEON_${NEONSITE}_hist_78pfts_CMIP6_simyr2000_c230601.nc" +fsurdat = "$DIN_LOC_ROOT/lnd/clm2/surfdata_esmf/NEON/surfdata_1x1_NEON_${NEONSITE}_hist_2000_78pfts_c240206.nc" ! h1 output stream hist_fincl2 = 'AR','ELAI','FCEV','FCTR','FGEV','FIRA','FSA','FSH','GPP','H2OSOI', diff --git a/doc/.ChangeLog_template b/doc/.ChangeLog_template index a1170a61cf..d7ba696835 100644 --- a/doc/.ChangeLog_template +++ b/doc/.ChangeLog_template @@ -18,6 +18,8 @@ Does this tag change answers significantly for any of the following physics conf [Put an [X] in the box for any configuration with significant answer changes.] +[ ] clm6_0 + [ ] clm5_1 [ ] clm5_0 @@ -31,9 +33,7 @@ Bugs fixed ---------- [Remove any lines that don't apply. Remove entire section if nothing applies.] -CTSM issues fixed (include CTSM Issue #): - -Known bugs introduced in this tag (include issue #): +List of CTSM issues fixed (include CTSM Issue # and description) [one per line]: Notes of particular relevance for users --------------------------------------- @@ -69,11 +69,7 @@ Testing summary: Nearly all CTSM tags should undergo 'regular' (aux_clm) testing. However, it occasionally makes sense to do more or less system testing; here is guidance on different available levels of system testing: - a) no system testing (for use when the only changes are ones that - have absolutely no impact on system runs; this - includes documentation-only tags, tags that - just change the tools or some python code that - does not impact system runs, etc.) + a) no system testing (this would normally be something that would go to the b4b-dev branch) b) minimal (for use in rare cases where only a small change with known behavior is added ... eg. a minor bug fix. This might be to just run the "short" test list, or to run @@ -82,10 +78,10 @@ here is guidance on different available levels of system testing: run the python testing listed below) d) regular (regular tests on normal machines if CTSM source is modified) e) release (regular tests plus the fates, ctsm_sci, mosart and rtm test lists - and normally all of the ancillary tests (build-namelist, python, ptclm, etc.) - would be run as well) + and normally all of the ancillary tests (build-namelist, python, etc.) + would be run as well) -In addition, various other tests of the tools, python and perl +In addition, various other tests of the tools, python and namelist script infrastructure should be run when appropriate, as described below. ...] @@ -98,10 +94,6 @@ infrastructure should be run when appropriate, as described below. derecho - - tools-tests (test/tools) (if tools have been changed): - - derecho - - python testing (if python code has changed; see instructions in python/README.md; document testing done): (any machine) - @@ -127,6 +119,9 @@ infrastructure should be run when appropriate, as described below. any other testing (give details below): + ctsm_sci + derecho ---- + If the tag used for baseline comparisons was NOT the previous tag, note that here: diff --git a/doc/.release-ChangeLog_template b/doc/.release-ChangeLog_template index 7f818c7c25..73c9c99e35 100644 --- a/doc/.release-ChangeLog_template +++ b/doc/.release-ChangeLog_template @@ -32,41 +32,31 @@ Testing: build-namelist tests: - cheyenne - + derecho - unit-tests (components/clm/src): - cheyenne - + derecho - izumi ---- - tools-tests (components/clm/test/tools): - - cheyenne - - izumi ---- - - PTCLM testing (components/clm/tools/shared/PTCLM/test): - - cheyenne - - izumi ---- - regular tests (aux_clm): - cheyenne_intel ---- - cheyenne_gnu ------ + derecho_intel ---- + derecho_gnu ------ izumi_nag --------- izumi_pgi --------- izumi_intel ------- regular tests (prealpha): - cheyenne_intel - - cheyenne_gnu --- + derecho_intel - + derecho_gnu --- izumi_nag ------ regular tests (prebeta): - cheyenne_intel - - cheyenne_gnu --- + derecho_intel - + derecho_gnu --- izumi_nag ------ Summary of Answer changes: diff --git a/doc/ChangeLog b/doc/ChangeLog index d58d7150dd..ce1a4f4815 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,4 +1,259 @@ =============================================================== +Tag name: ctsm5.2.0 +Originator(s): many (see below) +Date: Sat 20 Apr 2024 12:33:33 AM MDT +One-line Summary: New surface datasets and new mksurfdata_esmf tool to create them + +Purpose and description of changes +---------------------------------- + +Changes to CTSM: +================ + +All new surface datasets. Transient urban and lake by default turned on for transient cases. +Ocean is run as baresoil rather than wetland (for clm6_0). The urban streams file was also +updated. The new surface datasets have new updated input datasets (see below). + +Update the README files. + +New surface datasets: +===================== + +The new surface datasets are incompatible with previous versions (for example the ctsm5.1 series) +ctsm5.2.0 and following versions also can NOT use the previous ctsm5.1 datasets. + +See the section below about the new datasets used in their creation. Improvements in how landunits +on coastal areas was also done. + +The following fields were added and removed to the list of fields on the datasets. + +Fields added: + ORGC, BULK, CFRAG, PHAQ (soil data) (currently NOT used by CTSM) + mapunits (map units from the soil dataset) + LANDFRAC_MKSURFDATA (for reference NOT used by CTSM) + PCT_OCEAN (previously PCT_WETLAND was used) + +Fields removed: + AREA, PFTDATA_MASK + +New mksurfdata_esmf Tool: +========================= + +Implement a parallel version of mksurfdata (mksurfdata_esmf) that uses ESMF regridding directly +in mksurfdata so that offline mapping files don't have to be created as a separate step. This +allows mksurfdata to create surface datasets at much higher resolutions + +The build for the tool is based on the CESM/CIME build system and uses cmake. This allows the build +to be kept up with changes in CESM. Currently it's only setup and working on Derecho. But, this design +will enable it to be built and run on any CESM supported machine (or a machine that a user ports to). + +Any input grid from ccs_config can be used, or the user can supply their own mesh file to define +the output grid. The user no longer has to add to the list of valid resolutions as in mksurfdata_map. + +Creation of supported single point datasets. These datasets are created through the use of subset_data. + +Test datasets for dynUrban, dynLake, and dynPFT is done with a simple NCO script. + +All datasets can be easily made by running "make all" in the tools/mksurfdata_esmf directory. + +For instructions see: + tools/mksurfdata_esmf/README.md + +New input datasets to mksurfdata_esmf: +====================================== + +New soil dataset: ISRIC/WISE dataset Batjes (2016) https://doi.org/10.1016/j.geoderma.2016.01.034 +New PFT, soil-color, LAI dataset: Created by Lawrence P.J. 2022 +New Glacier datasets: Glacier outlines from RGI version 6 (Arendt et al., 2017). + vector data for GrIS and AIS retrieved from BedMachine version 4 and version 2 (Morlighem et al., 2017, 2020), respectively. + 30-arcsec topography/land mask retrieved GMTED2010 (Danielson and Gesch, 2011). +New urban datasets: Gao and O'Neill (2021) and Gao and Pesaresi (2022), Oleson and Feddema (2020) +New lake datasets: HydroLake: Messager et. al. (2016) + +Contributors +------------ +@mvertens @ekluzek @slevis-lmwg @jedwards4b @billsacks @wwieder @lawrencepj1 @negin513 @dlawrenncar @olyson +@keerzhang1 @fang-bowen @Face2sea @adamrher @samsrabin + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[x] clm6_0 (new) + +[x] clm5_1 + +[x] clm5_0 + +[x] ctsm5_0-nwp + +[x] clm4_5 + + +Bugs fixed +---------- + +CTSM issues fixed (include CTSM Issue #): + Fixes #1903 Create new surface datasets, CTSM5.2 branch + Fixes #1716 Wetland area and areas of landunits in coastal grid cells + should be determined more rigorously + Fixes #1556 Remake PCT_PFT raw datasets to NOT force landunit area to 100%, + and some other fixes needed to PCT_PFT raw datasets + Fixes #1878 Convert wetlands to bare ground + Fixes #2131 Add a "successfully completed" message to mksurfdata_esmf when + the landuse.timeseries file is made + Fixes #2218 CTSM5.2 branch dies weirdly when clm5.0/ctsm5.1 datasets are + used -- die with an error + Fixes #1483 hcru surface datasets + Fixes #2228 sys test requirements for mksurfdata_esmf + Fixes #90 Remove need for fatmgrid + Fixes #80 Improve modularity of mksurfdata_map + Fixes #1878 Convert wetlands to bare-ground + +Notes of particular relevance for users +--------------------------------------- + +Caveats for users (e.g., need to interpolate initial conditions): + These surface datasets can NOT be used in previous versions of the model + Older surface datasets can NOT be used with this model version + + IMPORTANT NOTE FOR USERS FOR REGIONAL CASES: + Because of this issue: + + https://github.com/ESCOMP/CTSM/issues/2430 + + We recommend that users use subset_data to subset your region from a global + grid. This could mean creating a global grid at the resolution you need (if + not standard) and then use subset_data on it to get the region of + interest. + +Changes to CTSM's user interface (e.g., new/renamed XML or namelist variables): + New CLM_PHYSICS_VERSION option of clm6_0 added (use it rather than clm5_1) + New compsets for Clm60 added + New namelist item: convert_ocean_to_land (default true for clm5_1 and clm6_0 physics) + +Changes made to namelist defaults (e.g., changed parameter values): + clm5_1 physics options copied to clm6_0 + do_transient_lake and do_transient_urban set to TRUE for transient cases + +Changes to the datasets (e.g., parameter, surface or initial files): + New ctsm6.0 parameter file copied from the ctsm5.1 verison + fsurdat and landuse.timeseries datasets all updated + urbantv streams datasets updated + Some initial condition datasets updated to go with the new datasets + +Things being deprecated (which will be removed): + manage_externlas will be removed for git submodules + mkmapgrids and other NCL scripts + tools/test directory + +Notes of particular relevance for developers: +--------------------------------------------- + +Caveats for developers (e.g., code that is duplicated that requires double maintenance): + The namelist_defaults_ctsm.xml file was simplified which should make it easier to work with +Changes to tests or testing: + New system test in prealpha and aux_clm to create a surface dataset and run with it + ctsm_sci testlist updated to run all CESM3 supported datasets + See this document for the list of supported grids: + https://docs.google.com/spreadsheets/d/1Osq56e423CF107zhoNQ0VS7-iH_JXLF9AtCvBdXyfJ4 + +Testing summary: regular ctsm_sci fates mosart rtm tools python +---------------- + + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + build-namelist tests (if CLMBuildNamelist.pm has changed): + + derecho - PASS (1396 tests compare different because of the namelist changes) + + python testing (if python code has changed; see instructions in python/README.md; document testing done): + + derecho - PASS + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + derecho ----- OK + izumi ------- OK + + fates tests: (fates-sci.1.72.2_api.34.0.0-ctsm5.2.0) + derecho ----- OK + izumi ------- OK + + any other testing (give details below): + + mksurfdata_esmf + derecho ---- run "make all" to create all datasets (completes in 2-6 hours) + (crop-global-SSP2-4.5-ne30 was longest at 6 hr, most completed in 3.5 hours) + + ctsm_sci (ctsm_sci-ctsm5.2.0) + derecho ---- PASS + + rtm (rtm1_0_79_ctsm5.2.0) + derecho ---- PASS + + mosart (mosart1_0_49_ctsm5.2.0) + derecho ---- OK + izumi ----- PASS + +If the tag used for baseline comparisons was NOT the previous tag, note that here: ctsm5.1.dev176 + +Answer changes +-------------- + +Changes answers relative to baseline: Yes! + + Summarize any changes to answers, i.e., + - what code configurations: All + - what platforms/compilers: All + - nature of change: new climate + + Discussion on the new datasets and new results are here: + + https://github.com/ESCOMP/CTSM/discussions/1868 + + It includes case comparision + +Other details +------------- + +Pull Requests that document the changes (include PR ids): +(https://github.com/ESCOMP/ctsm/pull) + + #2464 -- Update ctsm5.2 branch to ctsm5.1.dev176 and some small updates + #2417 -- Addition of clm6_0 physics option + #2447 -- Update ctsm5.2 branch to ctsm5.1.dev175 + #2427 -- Merge ctsm5.2 branch up to ctsm5.1.dev174 + #2424 -- Clean up "make all" for 5.2 branch tag: bfb type: code cleanup + #2318 -- Workaround for transient Smallville tests #1673 + testing all new datasets + #1586 -- Enable the mksurfdata_map to generate landuse_timeseries for dynamic urban and lake + #2327 -- Working on Derecho + #2008 -- Get the Makefile working for CTSM5.2 surface dataset creation + #2164 -- Distinguish between ocean and wetland in fsurdat files + #2016 -- Preparing alpha-ctsm5.2.mksrf.16_ctsm5.1.dev123 tag + #1946 -- Newest raw datasets for pft, lai, soilcolor + #1873 -- Ctsm52 various updates + #1920 -- mksurfdata: Rework mapping of landunits to handle coastal areas more rigorously + #1890 -- Add option to convert wetlands to land; apply it by default for CLM51 physics + #1866 -- Remove pftmask from history and PFTDATA_MASK from fsurdat files + #1732 -- New soiltex for ctsm5.2.mksurfdata + #1853 -- Implement GaoOneill raw urban datasets and OlesonFeddema urban + properties into mksurfdata_esmf. + #1796 -- Add consistency checks for mesh_nx mesh_ny relative to mesh_file in + gen_mksurfdata_namelist.py + #1748 -- Enable mksurfdata esmf to build and run on casper and izumi + #1756 -- Add mksurfdata_esmf system test to test-suite tag: support tools only + #1721 -- cmake build working on cheyenne for mksurfdata_esmf + #1746 -- Change repo_url from git@... to https:... for ccs_config + #1728 -- Accelerate generation of transient data with mksurfdata_esmf + #1663 -- New parallel surface dataset generation with online regridding + +=============================================================== +=============================================================== Tag name: ctsm5.1.dev176 Originator(s): afoster (Adrianna Foster,UCAR/TSS,303-497-1728) Date: Thu 04 Apr 2024 06:29:36 PM MDT diff --git a/doc/ChangeSum b/doc/ChangeSum index 2464a4980f..00b4277647 100644 --- a/doc/ChangeSum +++ b/doc/ChangeSum @@ -1,5 +1,6 @@ Tag Who Date Summary ============================================================================================================================ + ctsm5.2.0 many 04/20/2024 New mksurfdata_esmf tool to create new surface datasets that are in place ctsm5.1.dev176 afoster 04/04/2024 Merge b4b-dev ctsm5.1.dev175 slevis 03/21/2024 merge-b4bdev-20240321 ctsm5.1.dev174 olyson 03/14/2024 Improve vegetation health at high latitudes diff --git a/doc/IMPORTANT_NOTES b/doc/IMPORTANT_NOTES index 276723d843..8d100f6a56 100644 --- a/doc/IMPORTANT_NOTES +++ b/doc/IMPORTANT_NOTES @@ -1,5 +1,5 @@ -$CTSMROOT/doc/IMPORTANT_NOTES Jun/08/2018 - Erik Kluzek +$CTSMROOT/doc/IMPORTANT_NOTES Apr/19/2024 + Erik Kluzek Namelist items that are not regularly tested or used. Some aren't even implemented. @@ -13,31 +13,46 @@ Namelist items that are not regularly tested or used. Some aren't even implement allowlakeprod carbon_resp_opt ch4offline - fin_use_fsat - lake_decomp_fact + do_sno_oc + finundation_method = h2osfc no_frozen_nitrif_denitrif perchroot perchroot_alt reduce_dayl_factor replenishlakec + snicar_dust_optics /= sahara + snicar_numrad_snw /= 5 + snicar_snobc_intmix /= TRUE + snicar_snodst_intmix /= TRUE + snicar_snw_shape /= hexagonal_plate + snicar_solarspec /= mid_latitude_winter + snicar_use_aerosol /= FALSE urban_traffic + usefrootc + use_cndv (deprecated) use_extralakelayers - use_lai_streams - use_cndv - use_snicar_frc + use_soil_moisture_streams use_vichydro - usefrootc vcmax_opt = 4 FATES namelist options: FATES is a new experiemental subcomponent where all of it's options are under current development. As such FATES and all of it's options should be considered experimental. + fates_history_dimlevel + fates_inventory_ctrl_filename + fates_parteh_mode + fates_spitfire_mode use_fates - use_fates_spitfire + use_fates_cohort_age_tracking + use_fates_ed_prescribed_phys + use_fates_ed_st3 + use_fates_fixed_biogeog use_fates_logging + use_fates_luh + use_fates_nocomp use_fates_planthydro - use_fates_ed_st3 - use_fates_ed_prescribed_phys + use_fates_sp + use_fates_spitfire + use_fates_tree_damage use_fates_inventory_init - fates_inventory_ctrl_filename diff --git a/doc/Quickstart.GUIDE b/doc/Quickstart.GUIDE index f574d1184f..4b2a7b226b 100644 --- a/doc/Quickstart.GUIDE +++ b/doc/Quickstart.GUIDE @@ -1,10 +1,10 @@ -$CTSMROOT/doc/Quickstart.GUIDE Jun/08/2018 +$CTSMROOT/doc/Quickstart.GUIDE Apr/19/2024 - Quick-Start to Using NUOPC Scripts for clm5_0 - ============================================ + Quick-Start to Using NUOPC Scripts for ctsm6_0 + ============================================== -Assumptions: You want to use cheyenne with clm5_0 BGC - to do a clm simulation with data atmosphere and the +Assumptions: You want to use derecho with ctsm_0 BGC + to do a CTSM climate simulation with data atmosphere and the latest GSWP3v1 atm forcing files and settings. You also want to cycle the GSWP3v1 atm data between 1950 to 2010 and you want to run at 0.9x1.25 degree resolution. @@ -15,7 +15,7 @@ Process: cd cime/scripts - ./create_newcase --case --mach cheyenne --res f09_g16_gl4 -compset I2000Clm50BgcCrop + ./create_newcase --case --mach derecho --res f09_g16_gl4 -compset I2000Clm60BgcCrop (./create_newcase -help -- to get help on the script) # Setup the case @@ -39,8 +39,8 @@ Process: Information on Compsets: - "I" compsets are the ones with clm and NUOPC driver and CDEPS data models without ice and ocean. - Most of the "I" compsets for CLM5.0 use the GSWP3v1 data with solar following + "I" compsets are the ones with CTSM and NUOPC driver and CDEPS data models without ice and ocean. + Most of the "I" compsets for ctsm5.0 physics and use the GSWP3v1 data with solar following the cosine of solar zenith angle, precipitation constant, and other variables linear interpolated in time (and with appropriate time-stamps on the date). diff --git a/doc/UpdateChangelog.pl b/doc/UpdateChangelog.pl index 4a5329175b..67be182b8d 100755 --- a/doc/UpdateChangelog.pl +++ b/doc/UpdateChangelog.pl @@ -67,7 +67,8 @@ sub usage { $tag = $ARGV[0]; $sum = $ARGV[1]; - if ( $tag !~ /ctsm[0-9]\.[0-9]\.(dev[0-9][0-9][0-9]|[0-9][0-9])/ ) { + # Tags should be something like ctsm5.3.dev001 or ctsm5.3.0 + if ( ($tag !~ /ctsm[0-9]\.[0-9]\.(dev[0-9][0-9][0-9]|[0-9][0-9])/) && ($tag !~ /ctsm[0-9]\.([0-9])\.([0-9])/) ) { print "ERROR: bad tagname: $tag\n"; usage(); } diff --git a/doc/design/surface_dataset_areas.rst b/doc/design/surface_dataset_areas.rst new file mode 100644 index 0000000000..de12f951da --- /dev/null +++ b/doc/design/surface_dataset_areas.rst @@ -0,0 +1,69 @@ +.. sectnum:: + +.. contents:: + +================================== + Overview of this design document +================================== + +This document gives a high-level overview of the specification of sub-grid areas on surface datasets and the raw datasets used to create them. + +See also https://github.com/ESCOMP/CTSM/issues/1716 for related discussion. + +================================================= + Specification of landunit areas in raw datasets +================================================= + +In the high-resolution raw datasets used as input to the mksurfdata tool, landunit areas should be specified as percent of the grid cell, **not** percent of the land area. For example, on the urban raw dataset, if there is a grid cell that is 50% land and 50% ocean, and 60% of the land area is urban, the urban area in that grid cell should be given as 30%. + +One reason for this is that it makes reconciling the different landunit areas more straightforward if different raw datasets disagree about the land mask. In addition, this convention makes it easier to map raw datasets to the model resolution. For example, consider averaging two grid cells into a destination grid cell: one with 2% land area, of which 50% is glacier; and one with 100% land area, of which none is glacier. If we encode these as percent of the land area, we would have 50% glacier and 0% glacier, and then the final glacier cover would be 25%, suggesting that 25% of the land area is glacier, but this is incorrect. If we instead encode these as percent of the total grid cell area, we would have 1% glacier and 0% glacier, and then the final glacier cover would be 0.5%, suggesting that 0.5% of the total grid cell is glacier, which is correct. + +===================================================== + Specification of landunit areas in surface datasets +===================================================== + +In contrast to the raw datasets, landunit areas in surface datasets are specified as percent of the land area, **not** as percent of the total grid cell. This is because we don't know what the model's actual land fraction will be at the time when the surface datasets are created: instead, this land fraction is determined at runtime based on the ocean grid. + +=========================================================================================== + Procedure for converting landunit areas from percent of grid cell to percent of land area +=========================================================================================== + +There are a few important aspects to how we determine final landunit areas in mksurfdata: + +When mapping landunit areas from the raw data resolution to the model resolution, we initially want to maintain areas as percent of the total grid cell area. To achieve this, we set ``norm_by_fracs=.false.`` in the call to ``create_routehandle``, resulting in the use of ``ESMF_NORMTYPE_DSTAREA`` rather than ``ESMF_NORMTYPE_FRACAREA`` as a ``normType`` when computing mapping weights. Using ``FRACAREA`` normalization is appropriate when you want to treat areas outside of the source mask as missing values that do not contribute in any way to the final destination value. Using ``DSTAREA`` normalization, in contrast, essentially treats areas outside of the source mask as zeroes. ``FRACAREA`` normalization is appropriate for many surface dataset fields, but ``DSTAREA`` is appropriate for areas specified as percent of the grid cell. For example, if a source grid cell is entirely ocean, then we want to treat glacier area in that source grid cell as 0%. + +The conversion from percent of the grid cell area to percent of the land area happens in the subroutine ``normalize_and_check_landuse``. An important piece of doing this conversion is to determine an estimate of the land fraction for each model grid cell. This is not straightforward given the disparate land masks used for each raw dataset. We start by using the land fraction from the vegetation (PFT) raw dataset, with the assumption that that is probably the most reliable land mask. However, there are areas where using that land fraction is problematic, particularly where the areas of other landunits extend beyond the PFT's land mask. This is especially an issue for glaciers, where floating ice shelves can extend beyond the land-ocean border. To deal with this problem, if the sum of the areas of special landunits and crops exceeds the land fraction from the PFT data, we instead use that sum as an estimate of the land fraction. Exactly which landunits to include in this sum is a bit arbitrary. Arguably, the natural vegetated landunit should also be included in this sum. However, we ideally want to avoid changes in this estimated land fraction through time in transient datasets, which means that we generally want to use the PFT data's land fraction, only falling back on this landunit sum in exceptional cases. By excluding the natural vegetated area from this sum, we are more likely to use the PFT's land fraction. An implication of this choice is that we are more likely to replace natural vegetated areas with special landunits in cases where there are disagreements between the different raw datasets in coastal grid cells. For more detailed explanation and rationale, see some comments in ``normalize_and_check_landuse``. + +In grid cells where the estimated land fraction is essentially zero, we set the land cover to wetland, as a rough parameterization of ocean. This situation will only arise if the areas of all landunits on the raw datasets are essentially zero for the given grid cell, so we would have no information to choose any particular land cover for the grid cell. (This wetland area may end up being changed to bare ground at runtime, depending on the value of the ``convert_ocean_to_land`` namelist flag.) + +In grid cells where the estimated land fraction is greater than zero, we fill any unclaimed land area with the natural vegetated landunit. We then normalize all landunit areas based on the estimated land fraction so that they now specify areas as percent of the land area rather than as percent of the grid cell. + +=================== + Example scenarios +=================== + +The following example scenarios illustrate the operation of ``normalize_and_check_landuse``; in the following, any landunit not explicitly mentioned has 0% area: + +(a) With pctlnd_pft = 0% and all initial landunit areas 0%: wetland area = 100% + +(b) With pctlnd_pft = 0% and initial glacier area 1%: glacier area = 100% + +(c) With pctlnd_pft > 0% and all initial landunit areas 0%: natural vegetated area = 100% + +(d) With pctlnd_pft = 40%, initial crop area 20%, natural vegetated area 10%: crop area = 50%, natural vegetated area = 50% + +(e) With pctlnd_pft = 40%, initial crop area 20%, natural vegetated area 10%, glacier area 10%: crop area = 50%, natural vegetated area = 25%, glacier area = 25% + +(f) With pctlnd_pft = 40%, initial crop area 20%, natural vegetated area 10%, glacier area 15%: crop area = 50%, natural vegetated area = 12.5%, glacier area = 37.5% + +(g) With pctlnd_pft = 40%, initial crop area 20%, natural vegetated area 10%, glacier area 20%: crop area = 50%, glacier area = 50% + +(h) With pctlnd_pft = 40%, initial crop area 20%, natural vegetated area 10%, glacier area 30%: crop area = 40%, glacier area = 60% + +(i) With pctlnd_pft = 40%, initial crop area 0%, natural vegetated area 40%, glacier area 40%: glacier area = 100% + +(j) With pctlnd_pft = 2%, initial natural vegetated area 1%, glacier area 1%: natural vegetated area = 50%, glacier area = 50% + +(k) With pctlnd_pft = 2%, initial natural vegetated area 0%, glacier area 1%: natural vegetated area = 50%, glacier area = 50% + +(l) With pctlnd_pft = 2%, initial natural vegetated area 2%, glacier area 1%: natural vegetated area = 50%, glacier area = 50% diff --git a/doc/source/lilac/specific-atm-models/wrf-tools.rst b/doc/source/lilac/specific-atm-models/wrf-tools.rst index 0366bc1582..f67a05ea0a 100644 --- a/doc/source/lilac/specific-atm-models/wrf-tools.rst +++ b/doc/source/lilac/specific-atm-models/wrf-tools.rst @@ -52,9 +52,9 @@ is described in here. ./gen_domain -m /glade/work/$USER/ctsm/nldas_grid/scrip/wrf2clm_mapping_noneg.nc -o wrf2clm_ocn_noneg -l wrf2clm_lnd_noneg -6. Create surface datasets in ``tools/mksurfdata_map``:: +6. Create surface datasets in ``tools/mksurfdata_esmf``:: - ./mksurfdata.pl -res usrspec -usr_gname "nldas" -usr_gdate "190124" -usr_mapdir "/glade/work/$USER/ctsm/nldas_grid/map" -y 2000 -exedir "/glade/u/home/$USER/src/ctsm/ctsm_surfdata/tools/mksurfdata_map" -no-crop + ./mksurfdata.pl -res usrspec -usr_gname "nldas" -usr_gdate "190124" -usr_mapdir "/glade/work/$USER/ctsm/nldas_grid/map" -y 2000 -exedir "/glade/u/home/$USER/src/ctsm/ctsm_surfdata/tools/mksurfdata_esmf" -no-crop Merge WRF initial conditions into an existing CTSM initial condition file -------------------------------------------------------------------------- diff --git a/doc/source/tech_note/Transient_Landcover/CLM50_Tech_Note_Transient_Landcover.rst b/doc/source/tech_note/Transient_Landcover/CLM50_Tech_Note_Transient_Landcover.rst index c221a14d28..99ee5ab676 100644 --- a/doc/source/tech_note/Transient_Landcover/CLM50_Tech_Note_Transient_Landcover.rst +++ b/doc/source/tech_note/Transient_Landcover/CLM50_Tech_Note_Transient_Landcover.rst @@ -107,9 +107,9 @@ To represent the LUH2 transient LULCC dataset in CLM5, the annual fractional com To support this translation task the CLM5 Land Use Data tool has been built that extends the methods described in Lawrence et al (2012) to include all the new functionality of CMIP6 and CLM5 LULCC. The tool translates each of the LUH2 land units for a given year into fractional PFT and CFT values based on the current day CLM5 data for the land unit in that grid cell. The current day land unit descriptions are generated from from 1km resolution MODIS, MIRCA2000, ICESAT, AVHRR, SRTM, and CRU climate data products combined with reference year LUH2 land unit data, usually set to 2005. Where the land unit does not exist in a grid cell for the current day, the land unit description is generated from nearest neighbors with an inverse distance weighted search algorithm. -The Land Use Data tool produces raw vegetation, crop, and management data files which are combined with other raw land surface data to produce the CLM5 initial surface dataset and the dynamic *landuse.timeseries* dataset with the CLM5 mksurfdata_map tool. The schematic of this entire process from LUH2 time series and high resolution current day data to the output of CLM5 surface datasets from the mksurfdata_map tool is shown in Figure 21.2. +The Land Use Data tool produces raw vegetation, crop, and management data files which are combined with other raw land surface data to produce the CLM5 initial surface dataset and the dynamic *landuse.timeseries* dataset with the CLM5 mksurfdata_esmf tool. The schematic of this entire process from LUH2 time series and high resolution current day data to the output of CLM5 surface datasets from the mksurfdata_esmf tool is shown in Figure 21.2. -The methodology for creating the CLM5 transient PFT and CFT dataset is based on four steps which are applied across all of the historical and future time series. The first step involves generating the current day descriptions of natural and managed vegetation PFTs at 1km resolution from the global source datasets, and the current day description of crop CFTs at the 10km resolution from the MIRCA 2000 datasets. The second step combines the current day (2005) LUH2 land units with the current day CLM5 PFT and CFT distributions to get CLM5 land unit descriptions in either PFTs or CFTs at the LUH2 resolution of 0.25 degrees. The third step involves combining the LUH2 land unit time series with the CLM5 PFT and CFT descriptions for that land unit to generate the CLM5 raw PFT and CFT time series in the *landuse.timeseries* file. At this point in the process management information in terms of fertilizer, irrigation and wood harvest are added to the CLM5 PFT and CFT data to complete the CLM5 raw PFT and CFT files. The final step is to combine these files with the other raw CLM5 surface data files in the mksurfdata_map tool. +The methodology for creating the CLM5 transient PFT and CFT dataset is based on four steps which are applied across all of the historical and future time series. The first step involves generating the current day descriptions of natural and managed vegetation PFTs at 1km resolution from the global source datasets, and the current day description of crop CFTs at the 10km resolution from the MIRCA 2000 datasets. The second step combines the current day (2005) LUH2 land units with the current day CLM5 PFT and CFT distributions to get CLM5 land unit descriptions in either PFTs or CFTs at the LUH2 resolution of 0.25 degrees. The third step involves combining the LUH2 land unit time series with the CLM5 PFT and CFT descriptions for that land unit to generate the CLM5 raw PFT and CFT time series in the *landuse.timeseries* file. At this point in the process management information in terms of fertilizer, irrigation and wood harvest are added to the CLM5 PFT and CFT data to complete the CLM5 raw PFT and CFT files. The final step is to combine these files with the other raw CLM5 surface data files in the mksurfdata_esmf tool. .. _Figure Schematic of land cover change: @@ -123,8 +123,8 @@ The methodology for creating the CLM5 transient PFT and CFT dataset is based on Schematic of translation of annual LUH2 land units to CLM5 plant and crop functional types. -.. _Figure Workflow of CLM5 Land Use Data Tool and Mksurfdata_map Tool: +.. _Figure Workflow of CLM5 Land Use Data Tool and mksurfdata_esmf Tool: .. figure:: image3.png - Workflow of CLM5 Land Use Data Tool and Mksurfdata_map Tool + Workflow of CLM5 Land Use Data Tool and mksurfdata_esmf Tool diff --git a/doc/source/tech_note/Urban/CLM50_Tech_Note_Urban.rst b/doc/source/tech_note/Urban/CLM50_Tech_Note_Urban.rst index e9bfb5eb57..8777c7be74 100644 --- a/doc/source/tech_note/Urban/CLM50_Tech_Note_Urban.rst +++ b/doc/source/tech_note/Urban/CLM50_Tech_Note_Urban.rst @@ -19,7 +19,7 @@ Present day global urban extent and urban properties were developed by :ref:`Jac For each of 33 distinct regions across the globe, thermal (e.g., heat capacity and thermal conductivity), radiative (e.g., albedo and emissivity) and morphological (e.g., height to width ratio, roof fraction, average building height, and pervious fraction of the canyon floor) properties are provided for each of the density classes. Building interior minimum and maximum temperatures are prescribed based on climate and socioeconomic considerations. The surface dataset creation routines (see CLM5.0 User's Guide) aggregate the data to the desired resolution. -An optional urban properties dataset, including a tool that allows for generating future urban development scenarios is also available (:ref:`Oleson and Feddema (2018) `). This will become the default dataset in future model versions. As described in :ref:`Oleson and Feddema (2018) ` the urban properties dataset in :ref:`Jackson et al. (2010) ` was modified with respect to wall and roof thermal properties to correct for biases in heat transfer due to layer and building type averaging. Further changes to the dataset reflect the need for scenario development, thus allowing for the creation of hypothetical wall types, and the easier interchange of wall facets. The new urban properties tool is available as part of the Toolbox for Human-Earth System Integration & Scaling (THESIS) tool set (http://www.cgd.ucar.edu/iam/projects/thesis/thesis-urbanproperties-tool.html; :ref:`Feddema and Kauffman (2016) `). The driver script (urban_prop.csh) specifies three input csv files (by default, mat_prop.csv, lam_spec.csv, and city_spec.csv; (:numref:`Figure schematic of THESIS urban properties tool`)) that describe the morphological, radiative, and thermal properties of urban areas, and generates a global dataset at 0.05° latitude by longitude in NetCDF format (urban_properties_data.05deg.nc). A standalone NCL routine (gen_data_clm.ncl) can be run separately after the mksurfdata_map tool creates the CLM surface dataset. This creates a supplementary streams file of setpoints for the maximum interior building temperature at yearly time resolution. +An optional urban properties dataset, including a tool that allows for generating future urban development scenarios is also available (:ref:`Oleson and Feddema (2018) `). This will become the default dataset in future model versions. As described in :ref:`Oleson and Feddema (2018) ` the urban properties dataset in :ref:`Jackson et al. (2010) ` was modified with respect to wall and roof thermal properties to correct for biases in heat transfer due to layer and building type averaging. Further changes to the dataset reflect the need for scenario development, thus allowing for the creation of hypothetical wall types, and the easier interchange of wall facets. The new urban properties tool is available as part of the Toolbox for Human-Earth System Integration & Scaling (THESIS) tool set (http://www.cgd.ucar.edu/iam/projects/thesis/thesis-urbanproperties-tool.html; :ref:`Feddema and Kauffman (2016) `). The driver script (urban_prop.csh) specifies three input csv files (by default, mat_prop.csv, lam_spec.csv, and city_spec.csv; (:numref:`Figure schematic of THESIS urban properties tool`)) that describe the morphological, radiative, and thermal properties of urban areas, and generates a global dataset at 0.05° latitude by longitude in NetCDF format (urban_properties_data.05deg.nc). A standalone NCL routine (gen_data_clm.ncl) can be run separately after the mksurfdata_esmf tool creates the CLM surface dataset. This creates a supplementary streams file of setpoints for the maximum interior building temperature at yearly time resolution. .. Figure 12.1. Schematic representation of the urban land unit diff --git a/doc/source/users_guide/running-PTCLM/adding-ptclm-site-data.rst b/doc/source/users_guide/running-PTCLM/adding-ptclm-site-data.rst index d085c2f689..b95831427f 100644 --- a/doc/source/users_guide/running-PTCLM/adding-ptclm-site-data.rst +++ b/doc/source/users_guide/running-PTCLM/adding-ptclm-site-data.rst @@ -38,7 +38,7 @@ There is a mechanism for giving site-specific land-use change in PTCLMmkdata. Ad trans_year,pft_f1,pft_c1,pft_f2,pft_c2,pft_f3,pft_c3,pft_f4,pft_c4,pft_f5,pft_c5,har_vh1,har_vh2,har_sh1,har_sh2,har_sh3,graze,hold_harv,hold_graze -This file only requires a line for each year where a transition or harvest happens. As in the "pftdata" file above "pft_f" refers to the fraction and "pft_c" refers to the PFT index, and only up to five vegetation types are allowed to co-exist. The last eight columns have to do with harvesting and grazing. The last two columns are whether to hold harvesting and/or grazing constant until the next transition year and will just be either 1 or 0. This file will be converted by the **PTCLM_sitedata/cnvrt_trnsyrs2_pftdyntxtfile.pl** script in the PTCLMmkdata directory to a format that **mksurfdata_map** can read that has an entry for each year for the range of years valid for the compset in question. +This file only requires a line for each year where a transition or harvest happens. As in the "pftdata" file above "pft_f" refers to the fraction and "pft_c" refers to the PFT index, and only up to five vegetation types are allowed to co-exist. The last eight columns have to do with harvesting and grazing. The last two columns are whether to hold harvesting and/or grazing constant until the next transition year and will just be either 1 or 0. This file will be converted by the **PTCLM_sitedata/cnvrt_trnsyrs2_pftdyntxtfile.pl** script in the PTCLMmkdata directory to a format that **mksurfdata_esmf** can read that has an entry for each year for the range of years valid for the compset in question. .. _converting-ameriflux-for-ptclmmkdata: diff --git a/doc/source/users_guide/running-single-points/running-single-point-configurations.rst b/doc/source/users_guide/running-single-points/running-single-point-configurations.rst index 8588da8b99..9d2b68456b 100644 --- a/doc/source/users_guide/running-single-points/running-single-point-configurations.rst +++ b/doc/source/users_guide/running-single-points/running-single-point-configurations.rst @@ -152,7 +152,7 @@ Example: Creating a surface dataset for a single point > ./mknoocnmap.pl -p 40,255 -n $GRIDNAME # Set pointer to MAPFILE just created that will be used later > setenv MAPFILE `pwd`/map_${GRIDNAME}_noocean_to_${GRIDNAME}_nomask_aave_da_${CDATE}.nc - # create the mapping files needed by mksurfdata_map. + # create the mapping files needed by mksurfdata_esmf. > cd ../.././mkmapdata > setenv GRIDFILE ../mkmapgrids/SCRIPgrid_${GRIDNAME}_nomask_${CDATE}.nc > ./mkmapdata.sh -r $GRIDNAME -f $GRIDFILE -t regional @@ -167,7 +167,7 @@ Example: Creating a surface dataset for a single point # Save the location where the domain file was created > setenv GENDOM_PATH `pwd` # Finally create the surface dataset - > cd ../../../../lnd/clm/tools/|version|/mksurfdata_map/src + > cd ../../../../lnd/clm/tools/|version|/mksurfdata_esmf/src > gmake > cd .. > ./mksurfdata.pl -r usrspec -usr_gname $GRIDNAME -usr_gdate $CDATE @@ -186,7 +186,7 @@ Example: Setting up a case from the single-point surface dataset just created > ./link_dirtree $CSMDATA $MYCSMDATA # Copy the file you created above to your new $MYCSMDATA location following the CLMUSRDAT # naming convention (leave off the creation date) - > cp $CESMROOT/$CTSMROOT/tools/mksurfdata_map/surfdata_${GRIDNAME}_simyr1850_$CDATE.nc \ + > cp $CESMROOT/$CTSMROOT/tools/mksurfdata_esmf/surfdata_${GRIDNAME}_simyr1850_$CDATE.nc \ $MYCSMDATA/lnd/clm2/surfdata_map/surfdata_${GRIDNAME}_simyr1850.nc > cd $CESMROOT/scripts > ./create_newcase -case my_usernldatasets_test -res CLM_USRDAT -compset I1850Clm50BgcCropCru \ diff --git a/doc/source/users_guide/running-special-cases/Running-with-irrigation.rst b/doc/source/users_guide/running-special-cases/Running-with-irrigation.rst index 12fa76af5b..f19b489731 100644 --- a/doc/source/users_guide/running-special-cases/Running-with-irrigation.rst +++ b/doc/source/users_guide/running-special-cases/Running-with-irrigation.rst @@ -6,7 +6,7 @@ Running with irrigation =================================== -In CLM4.0 irrigation isn't an allowed option. In CLM4.5 irrigation can ONLY be used WITH crop. With CLM5.0 irrigation can be used whether crop is on or not -- **BUT** if crop is off, your surface datasets **HAVE** to have irrigation defined appropriately. Right now *ALL* surface datasets without crop enabled have irrigation hard-wired on. In order to create datasets with irrigation off, you'd need to make changes to ``mksurfdata_map`` in order to have all generic crops to be non-irrigated. To turn on irrigation in |version| we simply add "-irrig on" to ``CLM_BLDNML_OPTS``. +In CLM4.0 irrigation isn't an allowed option. In CLM4.5 irrigation can ONLY be used WITH crop. With CLM5.0 irrigation can be used whether crop is on or not -- **BUT** if crop is off, your surface datasets **HAVE** to have irrigation defined appropriately. Right now *ALL* surface datasets without crop enabled have irrigation hard-wired on. In order to create datasets with irrigation off, you'd need to make changes to ``mksurfdata_esmf`` in order to have all generic crops to be non-irrigated. To turn on irrigation in |version| we simply add "-irrig on" to ``CLM_BLDNML_OPTS``. Example: Irrigation Simulation ------------------------------------------ diff --git a/doc/source/users_guide/using-clm-tools/building-the-clm-tools.rst b/doc/source/users_guide/using-clm-tools/building-the-clm-tools.rst index 09725c8afc..95e0333d6d 100644 --- a/doc/source/users_guide/using-clm-tools/building-the-clm-tools.rst +++ b/doc/source/users_guide/using-clm-tools/building-the-clm-tools.rst @@ -6,15 +6,15 @@ The CLM FORTRAN tools all have similar makefiles, and similar options for building. The tools **cprnc** and **gen_domain** use the CIME configure/build system which is described in the next section. -The Makefiles (for **mksurfdata_map** and **mkprocdata_map**) use GNU Make extensions and thus require that you use GNU make to use them. They also auto detect the type of platform you are on, using "uname -s" and set the compiler, compiler flags and such accordingly. There are also environment variables that can be set to set things that must be customized. All the tools use NetCDF and hence require the path to the NetCDF libraries and include files. On some platforms (such as Linux) multiple compilers can be used, and hence there are env variables that can be set to change the FORTRAN and/or "C" compilers used. The tools also allow finer control, by also allowing the user to add compiler flags they choose, for both FORTRAN and "C", as well as picking the compiler, linker and and add linker options. Finally the tools allow you to turn optimization on (which is off by default but on for **mksurfdata_map**) with the OPT flag so that the tool will run faster. +The Makefiles (for **mksurfdata_esmf** and **mkprocdata_map**) use GNU Make extensions and thus require that you use GNU make to use them. They also auto detect the type of platform you are on, using "uname -s" and set the compiler, compiler flags and such accordingly. There are also environment variables that can be set to set things that must be customized. All the tools use NetCDF and hence require the path to the NetCDF libraries and include files. On some platforms (such as Linux) multiple compilers can be used, and hence there are env variables that can be set to change the FORTRAN and/or "C" compilers used. The tools also allow finer control, by also allowing the user to add compiler flags they choose, for both FORTRAN and "C", as well as picking the compiler, linker and and add linker options. Finally the tools allow you to turn optimization on (which is off by default but on for **mksurfdata_esmf**) with the OPT flag so that the tool will run faster. -Options used by all: **mksurfdata_map** +Options used by all: **mksurfdata_esmf** - ``LIB_NETCDF`` -- sets the location of the NetCDF library. - ``INC_NETCDF`` -- sets the location of the NetCDF include files. - ``USER_FC`` -- sets the name of the FORTRAN compiler. -Options used by: **mkprocdata_map**, and **mksurfdata_map** +Options used by: **mkprocdata_map**, and **mksurfdata_esmf** - ``MOD_NETCDF`` -- sets the location of the NetCDF FORTRAN module. - ``USER_LINKER`` -- sets the name of the linker to use. @@ -69,7 +69,7 @@ More details on each environment variable. .. warning:: Note, that depending on the compiler answers may be different when SMP is activated. ``OPT`` - This variable flags if compiler optimization should be used when compiling the tool. It can be set to either ``TRUE`` or ``FALSE``, by default it is set to for both **mksurfdata_map** and **mkprocdata_map**. Turning this on should make the tool run much faster. + This variable flags if compiler optimization should be used when compiling the tool. It can be set to either ``TRUE`` or ``FALSE``, by default it is set to for both **mksurfdata_esmf** and **mkprocdata_map**. Turning this on should make the tool run much faster. .. warning:: Note, you should expect that answers will be different when ``OPT`` is activated. diff --git a/doc/source/users_guide/using-clm-tools/creating-input-for-surface-dataset-generation.rst b/doc/source/users_guide/using-clm-tools/creating-input-for-surface-dataset-generation.rst index 276394e2b9..a727631a6c 100644 --- a/doc/source/users_guide/using-clm-tools/creating-input-for-surface-dataset-generation.rst +++ b/doc/source/users_guide/using-clm-tools/creating-input-for-surface-dataset-generation.rst @@ -40,12 +40,12 @@ If you want to create a regular latitude/longitude single-point or regional grid See :numref:`Figure mknoocnmap.pl` for a visual representation of this process. -Creating mapping files for mksurfdata_map +Creating mapping files for mksurfdata_esmf ============================================== ``mkmapdata.sh`` uses the above SCRIP grid input files to create SCRIP mapping data files (uses ESMF). -The bash shell script ``$CTSMROOT/tools/mkmapgrids/mkmapdata.sh`` uses ``ESMF_RegridWeightGen`` to create a list of maps from the raw datasets that are input to ``mksurfdata_map``. Each dataset that has a different grid, or land-mask needs a different mapping file for it, but many different raw datasets share the same grid/land-mask as other files. Hence, there doesn't need to be a different mapping file for EACH raw dataset---just for each raw dataset that has a DIFFERENT grid or land-mask. See :numref:`Figure mkmapdata.sh` for a visual representation of how this works. The bash script figures out which mapping files it needs to create and then runs ``ESMF_RegridWeightGen`` for each one. You can then either enter the datasets into the XML database (see Chapter :numref:`adding-new-resolutions-section`), or leave the files in place and use the ``-res usrspec -usr_gname -usr_gdate`` options to ``mksurfdata_map``. ``mkmapdata.sh`` has a help option with the following +The bash shell script ``$CTSMROOT/tools/mkmapgrids/mkmapdata.sh`` uses ``ESMF_RegridWeightGen`` to create a list of maps from the raw datasets that are input to ``mksurfdata_esmf``. Each dataset that has a different grid, or land-mask needs a different mapping file for it, but many different raw datasets share the same grid/land-mask as other files. Hence, there doesn't need to be a different mapping file for EACH raw dataset---just for each raw dataset that has a DIFFERENT grid or land-mask. See :numref:`Figure mkmapdata.sh` for a visual representation of how this works. The bash script figures out which mapping files it needs to create and then runs ``ESMF_RegridWeightGen`` for each one. You can then either enter the datasets into the XML database (see Chapter :numref:`adding-new-resolutions-section`), or leave the files in place and use the ``-res usrspec -usr_gname -usr_gdate`` options to ``mksurfdata_esmf``. ``mkmapdata.sh`` has a help option with the following :: ../../tools/mkmapdata/mkmapdata.sh @@ -104,4 +104,4 @@ The bash shell script ``$CTSMROOT/tools/mkmapgrids/mkmapdata.sh`` uses ``ESMF_Re Details of running mkmapdata.sh -Each of the raw datasets for ``mksurfdata_map`` needs a mapping file to map from the output grid you are running on to the grid and land-mask for that dataset. This is what ``mkmapdata.sh`` does. To create the mapping files you need a SCRIP grid file to correspond with each resolution and land mask that you have a raw data file in ``mksurfdata_map``. Some raw datasets share the same grid and land mask -- hence they can share the same SCRIP grid file. The output maps created here go into ``mksurfdata_map`` see :numref:`Figure Workflow of CLM5 Land Use Data Tool and Mksurfdata_map Tool`. +Each of the raw datasets for ``mksurfdata_esmf`` needs a mapping file to map from the output grid you are running on to the grid and land-mask for that dataset. This is what ``mkmapdata.sh`` does. To create the mapping files you need a SCRIP grid file to correspond with each resolution and land mask that you have a raw data file in ``mksurfdata_esmf``. Some raw datasets share the same grid and land mask -- hence they can share the same SCRIP grid file. The output maps created here go into ``mksurfdata_esmf`` see :numref:`Figure Workflow of CLM5 Land Use Data Tool and mksurfdata_esmf Tool`. diff --git a/doc/source/users_guide/using-clm-tools/creating-surface-datasets.rst b/doc/source/users_guide/using-clm-tools/creating-surface-datasets.rst index cfaa8527cd..d2e2ef7c89 100644 --- a/doc/source/users_guide/using-clm-tools/creating-surface-datasets.rst +++ b/doc/source/users_guide/using-clm-tools/creating-surface-datasets.rst @@ -14,7 +14,7 @@ When just creating a replacement file for an existing one, the relevant tool sho Data Flow for Creation of Surface Datasets from Raw SCRIP Grid Files -Starting from a SCRIP grid file that describes the grid you will run the model on, you first run ```mkmapdata.sh`` to create a list of mapping files. See :numref:`Figure mkmapdata.sh` for a more detailed view of how ``mkmapdata.sh`` works. The mapping files tell ``mksurfdata_map`` how to map between the output grid and the raw datasets that it uses as input. The output of ``mksurfdata_map`` is a surface dataset that you then use for running the model. See :numref:`Figure Workflow of CLM5 Land Use Data Tool and Mksurfdata_map Tool` for a more detailed view of how ``mksurfdata_map`` works. +Starting from a SCRIP grid file that describes the grid you will run the model on, you first run ```mkmapdata.sh`` to create a list of mapping files. See :numref:`Figure mkmapdata.sh` for a more detailed view of how ``mkmapdata.sh`` works. The mapping files tell ``mksurfdata_esmf`` how to map between the output grid and the raw datasets that it uses as input. The output of ``mksurfdata_esmf`` is a surface dataset that you then use for running the model. See :numref:`Figure Workflow of CLM5 Land Use Data Tool and mksurfdata_esmf Tool` for a more detailed view of how ``mksurfdata_esmf`` works. :numref:`Figure Data_Flow_Legend` is the legend for this figure (:numref:`Figure Data_Flow`) and other figures in this chapter (:numref:`Figure Global-Domain` and :numref:`Figure mknoocnmap.pl`). @@ -26,7 +26,7 @@ Starting from a SCRIP grid file that describes the grid you will run the model o Green arrows define the input to a program, while red arrows define the output. Cylinders define files that are either created by a program or used as input for a program. Boxes are programs. -You start with a description of a SCRIP grid file for your output grid file and then create mapping files from the raw datasets to it. Once, the mapping files are created **mksurfdata_map** is run to create the surface dataset to run the model. +You start with a description of a SCRIP grid file for your output grid file and then create mapping files from the raw datasets to it. Once, the mapping files are created **mksurfdata_esmf** is run to create the surface dataset to run the model. Creating a Complete Set of Files for Input to CLM ------------------------------------------------- @@ -39,13 +39,13 @@ Creating a Complete Set of Files for Input to CLM Next use gen_domain to create a domain file for use by DATM and CLM. This is required, unless a domain file was already created. See the Section called Creating a domain file for CLM and DATM for more information on this. -3. Create mapping files for mksurfdata_map (if NOT already done) +3. Create mapping files for mksurfdata_esmf (if NOT already done) - Create mapping files for mksurfdata_map with mkmapdata.sh in $CTSMROOT/tools/mkmapdata. See the Section called Creating mapping files that mksurfdata_map will use for more information on this. + Create mapping files for mksurfdata_esmf with mkmapdata.sh in $CTSMROOT/tools/mkmapdata. See the Section called Creating mapping files that mksurfdata_esmf will use for more information on this. 4. Create surface datasets - Next use mksurfdata_map to create a surface dataset, using the mapping datasets created on the previous step as input. There is a version for either clm4_0 or |version| for this program. See the Section called Using mksurfdata_map to create surface datasets from grid datasets for more information on this. + Next use mksurfdata_esmf to create a surface dataset, using the mapping datasets created on the previous step as input. There is a version for either clm4_0 or |version| for this program. See the Section called Using mksurfdata_esmf to create surface datasets from grid datasets for more information on this. 5. Enter the new datasets into the build-namelist XML database The last optional thing to do is to enter the new datasets into the build-namelist XML database. See Chapter 3 for more information on doing this. This is optional because the user may enter these files into their namelists manually. The advantage of entering them into the database is so that they automatically come up when you create new cases. diff --git a/doc/source/users_guide/using-clm-tools/observational-sites-datasets.rst b/doc/source/users_guide/using-clm-tools/observational-sites-datasets.rst index 385ec159aa..50a7969281 100644 --- a/doc/source/users_guide/using-clm-tools/observational-sites-datasets.rst +++ b/doc/source/users_guide/using-clm-tools/observational-sites-datasets.rst @@ -6,6 +6,6 @@ Observational Sites Datasets ******************************* -There are two ways to customize datasets for a particular observational site. The first is to customize the input to the tools that create the dataset, and the second is to overwrite the default data after you've created a given dataset. Depending on the tool it might be easier to do it one way or the other. In Table :numref:`reqd-files-table` we list the files that are most likely to be customized and the way they might be customized. Of those files, the ones you are most likely to customize are: ``fatmlndfrc``, ``fsurdat``, ``faerdep`` (for DATM), and ``stream_fldfilename_ndep``. Note ``mksurfdata_map`` as documented previously has options to overwrite the vegetation and soil types. For more information on this also see :ref:`creating-your-own-singlepoint-dataset`. ``PTCLM`` uses these methods to customize datasets; see Chapter :numref:`running-PTCLM`. +There are two ways to customize datasets for a particular observational site. The first is to customize the input to the tools that create the dataset, and the second is to overwrite the default data after you've created a given dataset. Depending on the tool it might be easier to do it one way or the other. In Table :numref:`reqd-files-table` we list the files that are most likely to be customized and the way they might be customized. Of those files, the ones you are most likely to customize are: ``fatmlndfrc``, ``fsurdat``, ``faerdep`` (for DATM), and ``stream_fldfilename_ndep``. Note ``mksurfdata_esmf`` as documented previously has options to overwrite the vegetation and soil types. For more information on this also see :ref:`creating-your-own-singlepoint-dataset`. ``PTCLM`` uses these methods to customize datasets; see Chapter :numref:`running-PTCLM`. Another aspect of customizing your input datasets is customizing the input atmospheric forcing datasets; see :ref:`creating-your-own-singlepoint-dataset` for more information on this. :ref:`converting-ameriflux-for-ptclmmkdata` has information on using the AmeriFlux tower site data as atmospheric forcing. diff --git a/doc/source/users_guide/using-clm-tools/what-are-the-clm-tools.rst b/doc/source/users_guide/using-clm-tools/what-are-the-clm-tools.rst index 6921e4dafd..664e23a220 100644 --- a/doc/source/users_guide/using-clm-tools/what-are-the-clm-tools.rst +++ b/doc/source/users_guide/using-clm-tools/what-are-the-clm-tools.rst @@ -16,7 +16,7 @@ The list of generally important scripts and programs are as follows. #. *./mkmapdata* to create SCRIP mapping data file from SCRIP grid files (uses ESMF). -#. *mksurfdata_map* to create surface datasets from grid datasets (clm4_0 and |version| versions). +#. *mksurfdata_esmf* to create surface datasets from grid datasets (clm4_0 and |version| versions). #. *./mkprocdata_map* to interpolate output unstructured grids (such as the CAM HOMME dy-core "ne" grids like ne30np4) into a 2D regular lat/long grid format that can be plotted easily. Can be used by either clm4_0 or |version|. @@ -26,7 +26,7 @@ The list of generally important scripts and programs are as follows. In the sections to come we will go into detailed description of how to use each of these tools in turn. First, however we will discuss the common environment variables and options that are used by all of the FORTRAN tools. Second, we go over the outline of the entire file creation process for all input files needed by CLM for a new resolution, then we turn to each tool. In the last section we will discuss how to customize files for particular observational sites. -The FORTRAN tools (mksurfdata_map and mkprocdata_map) run, with a namelist (mksurfdata_map) to provide options, or with command line arguments (mkprocdata_map). +The FORTRAN tools (mksurfdata_esmf and mkprocdata_map) run, with a namelist (mksurfdata_esmf) to provide options, or with command line arguments (mkprocdata_map). In the following sections, we will outline how to make these files available for build-namelist so that you can easily create simulations that include them. In the chapter on single-point and regional datasets we also give an alternative way to enter new datasets without having to edit files. @@ -34,12 +34,12 @@ In the following sections, we will outline how to make these files available for Running FORTRAN tools with namelists ------------------------------------ -**mksurfdata_map** runs with a namelist that is read from standard input. Hence, you create a namelist and then run them by redirecting the namelist file into standard input as follows: +**mksurfdata_esmf** runs with a namelist that is read from standard input. Hence, you create a namelist and then run them by redirecting the namelist file into standard input as follows: :: ./program < namelist -There is a sample namelist called ``$CTSMROOT/tools/mksurfdata_map/mksurfdata_map.namleist`` that shows you what the namelist should look like. **mksurfdata_map** also has a script that creates the namelist and runs the program for you. Namelists that you create should be similar to the example namelist. The namelist values are also documented along with the other namelists in the: +There is a sample namelist called ``$CTSMROOT/tools/mksurfdata_esmf/mksurfdata_esmf.namleist`` that shows you what the namelist should look like. **mksurfdata_esmf** also has a script that creates the namelist and runs the program for you. Namelists that you create should be similar to the example namelist. The namelist values are also documented along with the other namelists in the: :: $CTSMROOT/bld/namelist_files/namelist_definition.xml`` file diff --git a/lilac/bld_templates/ctsm_template.cfg b/lilac/bld_templates/ctsm_template.cfg index 04ecce49ca..2cd018aa3c 100644 --- a/lilac/bld_templates/ctsm_template.cfg +++ b/lilac/bld_templates/ctsm_template.cfg @@ -26,7 +26,7 @@ finidat = UNSET # High-level configuration options # ------------------------------------------------------------------------ -# ctsm_phys: 'clm4_5', 'clm5_0', or 'clm5_1' +# ctsm_phys: 'clm4_5', 'clm5_0', 'clm5_1' or "clm6_0" ctsm_phys = clm5_0 # configuration: 'nwp' or 'clm' diff --git a/lilac/bld_templates/mosart_in b/lilac/bld_templates/mosart_in index 833e4f10f8..091ec69285 100644 --- a/lilac/bld_templates/mosart_in +++ b/lilac/bld_templates/mosart_in @@ -5,7 +5,7 @@ do_rtm = .true. do_rtmflood = .false. finidat_rtm = " " - frivinp_rtm = "/glade/p/cesmdata/cseg/inputdata/rof/mosart/MOSART_routing_Global_0.5x0.5_c170601.nc" + frivinp_rtm = "/glade/campaign/cesm/cesmdata/cseg/inputdata/rof/mosart/MOSART_routing_Global_0.5x0.5_c170601.nc" ice_runoff = .true. qgwl_runoff_option = "threshold" rtmhist_fexcl1 = "" diff --git a/python/ctsm/lilac_make_runtime_inputs.py b/python/ctsm/lilac_make_runtime_inputs.py index 15dc4dd5b9..71f3c9bbe4 100644 --- a/python/ctsm/lilac_make_runtime_inputs.py +++ b/python/ctsm/lilac_make_runtime_inputs.py @@ -28,7 +28,7 @@ -Specifies ctsm physics +Specifies ctsm physics """ @@ -157,7 +157,7 @@ def buildnml(cime_path, rundir): "buildnml_input", "ctsm_phys", ctsm_cfg_path, - allowed_values=["clm4_5", "clm5_0", "clm5_1"], + allowed_values=["clm4_5", "clm5_0", "clm5_1", "clm6_0"], ) configuration = get_config_value( config, diff --git a/python/ctsm/mksurfdata_download_input_data.py b/python/ctsm/mksurfdata_download_input_data.py new file mode 100644 index 0000000000..a492ffeda2 --- /dev/null +++ b/python/ctsm/mksurfdata_download_input_data.py @@ -0,0 +1,91 @@ +"""Functions implementing the download_input_data command for mksurfdata""" + +import argparse +import logging +import os +import re + +from CIME.case import Case # pylint: disable=import-error + +from ctsm.ctsm_logging import setup_logging_pre_config, add_logging_args, process_logging_args + +logger = logging.getLogger(__name__) + +# ======================================================================== +# Define some constants +# ======================================================================== + +# In surfdata.namelist, file names match this pattern: +_FILENAME = r" = '/" + +# ======================================================================== +# Public functions +# ======================================================================== + + +def main(): + """Main function called when download_input_data is run from the command-line""" + setup_logging_pre_config() + args = _commandline_args() + process_logging_args(args) + + download_input_data(rundir=args.rundir) + + +def download_input_data(rundir): + """Implementation of the download_input_data command + + Args: + rundir: str - path to directory containing .input_data_list file + """ + _create_input_data_list(rundir) + # TODO Remove hardwiring + case = Case(os.path.realpath("/home/slevis/cases_FATES/CZ2_acf_off")) + case.check_all_input_data(data_list_dir=rundir, download=True, chksum=False) + os.remove(os.path.join(rundir, ".input_data_list")) + + +# ======================================================================== +# Private functions +# ======================================================================== + + +def _commandline_args(): + """Parse and return command-line arguments""" + + description = """ +Script to download any missing input data for mksurfdata_esmf +""" + + parser = argparse.ArgumentParser( + description=description, formatter_class=argparse.RawTextHelpFormatter + ) + + parser.add_argument( + "--rundir", + default=os.getcwd(), + help="Full path of the run directory\n" + "(This directory should contain .input_data_list and surfdata.namelist,\n" + "among other files.)\n" + "(Note: it is assumed that this directory exists alongside the other\n" + "directories created by build_ctsm: 'case' and 'inputdata'.)", + ) + + add_logging_args(parser) + + args = parser.parse_args() + + return args + + +def _create_input_data_list(rundir): + with open(os.path.join(rundir, "surfdata.namelist"), encoding="utf-8") as namelist: + with open( + os.path.join(rundir, ".input_data_list"), "w", encoding="utf-8" + ) as input_data_list: + for line in namelist: + if re.search(_FILENAME, line): + # Remove quotes from filename, then output this line + line = line.replace('"', "") + line = line.replace("'", "") + input_data_list.write(line) diff --git a/python/ctsm/modify_input_files/fsurdat_modifier.py b/python/ctsm/modify_input_files/fsurdat_modifier.py index 6d350171cc..bd060cb9dc 100644 --- a/python/ctsm/modify_input_files/fsurdat_modifier.py +++ b/python/ctsm/modify_input_files/fsurdat_modifier.py @@ -110,7 +110,15 @@ def read_cfg_subgrid(config, cfg_path, numurbl=3): subgrid_settings = {} var_list = config.options(section) - valid_list = ["pct_natveg", "pct_crop", "pct_lake", "pct_glacier", "pct_wetland", "pct_urban"] + valid_list = [ + "pct_natveg", + "pct_crop", + "pct_lake", + "pct_glacier", + "pct_wetland", + "pct_urban", + "pct_ocean", + ] varsum = 0 for var in var_list: if valid_list.count(var) == 0: @@ -628,7 +636,9 @@ def fsurdat_modifier(parser): if process_var_list: varlist = read_cfg_var_list(config, idealized=idealized) - update_list = modify_fsurdat.check_varlist(varlist, allow_uppercase_vars=True) + update_list = modify_fsurdat.check_varlist( + varlist, allow_uppercase_vars=True, source="Config file: " + cfg_path + ) modify_fsurdat.set_varlist(update_list, cfg_path) logger.info("process_var_list is complete") else: diff --git a/python/ctsm/modify_input_files/modify_fsurdat.py b/python/ctsm/modify_input_files/modify_fsurdat.py index 53f06d7dc8..407d762d00 100644 --- a/python/ctsm/modify_input_files/modify_fsurdat.py +++ b/python/ctsm/modify_input_files/modify_fsurdat.py @@ -237,7 +237,9 @@ def set_dom_pft(self, dom_pft, lai, sai, hgt_top, hgt_bot): if val is not None: self.set_lai_sai_hgts(dom_pft=dom_pft, var=var, val=val) - def check_varlist(self, settings, allow_uppercase_vars=False): + def check_varlist( + self, settings, allow_uppercase_vars=False, source="input settings dictionary" + ): """ Check a list of variables from a dictionary of settings """ @@ -248,10 +250,10 @@ def check_varlist(self, settings, allow_uppercase_vars=False): val = settings[varname] if not var in self.file: if not allow_uppercase_vars: - errmsg = "Error: Variable " + varname + " is NOT in the file" + errmsg = "Error: Variable " + varname + " is NOT in the " + source abort(errmsg) if not varname.upper() in self.file: - errmsg = "Error: Variable " + varname.upper() + " is NOT in the file" + errmsg = "Error: Variable " + varname.upper() + " is NOT in the " + source abort(errmsg) varname = varname.upper() @@ -262,7 +264,10 @@ def check_varlist(self, settings, allow_uppercase_vars=False): if len(self.file[varname].dims) == 2: if not isinstance(val, float): abort( - "For 2D vars, there should only be a single value for variable = " + varname + "For 2D vars, there should only be a single value for variable = " + + varname + + " in " + + source ) elif len(self.file[varname].dims) >= 3: dim1 = int(self.file.sizes[self.file[varname].dims[0]]) @@ -273,10 +278,19 @@ def check_varlist(self, settings, allow_uppercase_vars=False): + str(dim1) + " for variable=" + varname + + " in " + + source ) if len(val) != dim1: abort( - "Variable " + varname + " is of the wrong size. It should be = " + str(dim1) + "Variable " + + varname + + " is " + + str(len(val)) + + " is of the wrong size. It should be = " + + str(dim1) + + " in " + + source ) return settings_return @@ -363,6 +377,7 @@ def zero_nonveg(self): self.setvar_lev0("PCT_WETLAND", 0) self.setvar_lev0("PCT_URBAN", 0) self.setvar_lev0("PCT_GLACIER", 0) + self.setvar_lev0("PCT_OCEAN", 0) def setvar_lev0(self, var, val): """ @@ -408,8 +423,8 @@ def set_idealized(self): max_sat_area = 0 # max saturated area std_elev = 0 # standard deviation of elevation slope = 0 # mean topographic slope - pftdata_mask = 1 landfrac_pft = 1 + landfrac_mksurfdata = 1 # if pct_nat_veg had to be set to less than 100, then each special # landunit would have to receive a unique pct value rather than the # common value used here in pct_not_nat_veg = 0 @@ -426,13 +441,14 @@ def set_idealized(self): self.setvar_lev0("SLOPE", slope) self.setvar_lev0("zbedrock", zbedrock) self.setvar_lev0("SOIL_COLOR", soil_color) - self.setvar_lev0("PFTDATA_MASK", pftdata_mask) self.setvar_lev0("LANDFRAC_PFT", landfrac_pft) + self.setvar_lev0("LANDFRAC_MKSURFDATA", landfrac_mksurfdata) self.setvar_lev0("PCT_WETLAND", pct_not_nat_veg) self.setvar_lev0("PCT_CROP", pct_not_nat_veg) self.setvar_lev0("PCT_LAKE", pct_not_nat_veg) self.setvar_lev0("PCT_URBAN", pct_not_nat_veg) self.setvar_lev0("PCT_GLACIER", pct_not_nat_veg) + self.setvar_lev0("PCT_OCEAN", pct_not_nat_veg) self.setvar_lev0("PCT_NATVEG", pct_nat_veg) for lev in self.file.nlevsoi: diff --git a/python/ctsm/modify_input_files/modify_mesh_mask.py b/python/ctsm/modify_input_files/modify_mesh_mask.py index a0dccedeb2..5c7e418ef7 100644 --- a/python/ctsm/modify_input_files/modify_mesh_mask.py +++ b/python/ctsm/modify_input_files/modify_mesh_mask.py @@ -101,16 +101,12 @@ def set_mesh_mask(self, var): "landmask not 0 or 1 at row, col, value = " + f"{row} {col} {landmask[row, col]}" ) - assert isclose(landmask[row, col], 0, abs_tol=1e-9) or isclose( - landmask[row, col], 1, abs_tol=1e-9 - ), errmsg + assert landmask[row, col] == 0 or landmask[row, col] == 1, errmsg errmsg = ( "mod_lnd_props not 0 or 1 at row, col, value = " + f"{row} {col} {mod_lnd_props[row, col]}" ) - assert isclose(mod_lnd_props[row, col], 0, abs_tol=1e-9) or isclose( - mod_lnd_props[row, col], 1, abs_tol=1e-9 - ), errmsg + assert mod_lnd_props[row, col] == 0 or mod_lnd_props[row, col] == 1, errmsg if int(mod_lnd_props[row, col]) == 1: errmsg = ( "landmask should = mod_lnd_props where the " diff --git a/python/ctsm/site_and_regional/modify_singlept_site_neon.py b/python/ctsm/site_and_regional/modify_singlept_site_neon.py index e69a8ab834..5c28bd3582 100755 --- a/python/ctsm/site_and_regional/modify_singlept_site_neon.py +++ b/python/ctsm/site_and_regional/modify_singlept_site_neon.py @@ -59,9 +59,10 @@ # -- valid neon sites -valid_neon_sites = glob.glob( +valid = glob.glob( os.path.join(path_to_ctsm_root(), "cime_config", "usermods_dirs", "NEON", "[!d]*") ) +valid_neon_sites = [x[-4:] for x in valid] # last 4 letters in each string def get_parser(): @@ -92,7 +93,7 @@ def get_parser(): dest="surf_dir", type=str, required=False, - default="/glade/scratch/" + myname + "/single_point/", + default="/glade/derecho/scratch/" + myname + "/single_point/", ) parser.add_argument( "--out_dir", @@ -104,7 +105,7 @@ def get_parser(): dest="out_dir", type=str, required=False, - default="/glade/scratch/" + myname + "/single_point_neon_updated/", + default="/glade/derecho/scratch/" + myname + "/single_point_neon_updated/", ) parser.add_argument( "--inputdata-dir", @@ -116,7 +117,7 @@ def get_parser(): dest="inputdatadir", type=str, required=False, - default="/glade/p/cesmdata/cseg/inputdata", + default="/glade/campaign/cesm/cesmdata/cseg/inputdata", ) parser.add_argument( "-d", @@ -223,9 +224,9 @@ def find_surffile(surf_dir, site_name, pft_16): """ if pft_16: - sf_name = "surfdata_1x1_NEON_" + site_name + "*hist_16pfts_Irrig_CMIP6_simyr2000_*.nc" + sf_name = "surfdata_1x1_NEON_" + site_name + "*hist_2000_16pfts*.nc" else: - sf_name = "surfdata_1x1_NEON_" + site_name + "*hist_78pfts_CMIP6_simyr2000_*.nc" + sf_name = "surfdata_1x1_NEON_" + site_name + "*hist_2000_78pfts*.nc" print(os.path.join(surf_dir, sf_name)) surf_file = sorted(glob.glob(os.path.join(surf_dir, sf_name))) @@ -282,7 +283,9 @@ def find_soil_structure(args, surf_file): # print (f_1.attrs["Soil_texture_raw_data_file_name"]) clm_input_dir = os.path.join(args.inputdatadir, "lnd/clm2/rawdata/") - surf_soildepth_file = os.path.join(clm_input_dir, f_1.attrs["Soil_texture_raw_data_file_name"]) + surf_soildepth_file = os.path.join( + clm_input_dir, f_1.attrs["soil_texture_lookup_raw_data_file_name"] + ) if os.path.exists(surf_soildepth_file): print( diff --git a/python/ctsm/site_and_regional/run_neon.py b/python/ctsm/site_and_regional/run_neon.py index d831f8dba2..6a3c585140 100755 --- a/python/ctsm/site_and_regional/run_neon.py +++ b/python/ctsm/site_and_regional/run_neon.py @@ -211,9 +211,9 @@ def main(description): res = "CLM_USRDAT" if run_type == "transient": - compset = "IHist1PtClm51Bgc" + compset = "IHist1PtClm60Bgc" else: - compset = "I1PtClm51Bgc" + compset = "I1PtClm60Bgc" # -- Looping over neon sites diff --git a/python/ctsm/site_and_regional/single_point_case.py b/python/ctsm/site_and_regional/single_point_case.py index 456bebee91..5dcec6c8e7 100644 --- a/python/ctsm/site_and_regional/single_point_case.py +++ b/python/ctsm/site_and_regional/single_point_case.py @@ -360,7 +360,7 @@ def create_landuse_at_point(self, indir, file, user_mods_dir): f_out = f_out.expand_dims(["lsmlat", "lsmlon"]) # specify dimension order - f_out = f_out.transpose("time", "cft", "natpft", "lsmlat", "lsmlon") + f_out = f_out.transpose("time", "cft", "natpft", "lsmlat", "lsmlon", "numurbl") # revert expand dimensions of YEAR year = np.squeeze(np.asarray(f_out["YEAR"])) @@ -425,6 +425,7 @@ def modify_surfdata_atpoint(self, f_orig): f_mod["PCT_WETLAND"][:, :] = 0.0 f_mod["PCT_URBAN"][:, :, :] = 0.0 f_mod["PCT_GLACIER"][:, :] = 0.0 + f_mod["PCT_OCEAN"][:, :] = 0.0 if self.dom_pft is not None: max_dom_pft = max(self.dom_pft) diff --git a/python/ctsm/subset_data.py b/python/ctsm/subset_data.py index 030cea2247..01053f6e1f 100644 --- a/python/ctsm/subset_data.py +++ b/python/ctsm/subset_data.py @@ -76,7 +76,7 @@ process_logging_args, ) -DEFAULTS_CONFIG = "tools/site_and_regional/default_data.cfg" +DEFAULTS_CONFIG = "tools/site_and_regional/default_data_2000.cfg" logger = logging.getLogger(__name__) diff --git a/python/ctsm/test/test_sys_fsurdat_modifier.py b/python/ctsm/test/test_sys_fsurdat_modifier.py index 0e11a204a8..d31537477e 100755 --- a/python/ctsm/test/test_sys_fsurdat_modifier.py +++ b/python/ctsm/test/test_sys_fsurdat_modifier.py @@ -46,7 +46,7 @@ def setUp(self): self._testinputs_path = testinputs_path self._fsurdat_in = os.path.join( testinputs_path, - "surfdata_5x5_amazon_16pfts_Irrig_CMIP6_simyr2000_c171214.nc", + "surfdata_5x5_amazon_hist_16pfts_CMIP6_2000_c231031.nc", ) self._tempdir = tempfile.mkdtemp() self._cfg_file_path = os.path.join(self._tempdir, "modify_fsurdat.cfg") @@ -78,8 +78,8 @@ def test_short_config(self): self._cfg_file_path = os.path.join(self._testinputs_path, "modify_fsurdat_short.cfg") sys.argv = ["fsurdat_modifier", self._cfg_file_path] parser = fsurdat_modifier_arg_process() - fsurdat_out = ( - "ctsm/test/testinputs/surfdata_5x5_amazon_16pfts_Irrig_CMIP6_simyr2000_c171214_out.nc" + fsurdat_out = os.path.join( + self._testinputs_path, "surfdata_5x5_amazon_hist_16pfts_CMIP6_2000_c231031.out.nc" ) if os.path.exists(fsurdat_out): os.remove(fsurdat_out) @@ -136,14 +136,14 @@ def test_opt_sections(self): self._cfg_file_path = os.path.join(self._testinputs_path, "modify_fsurdat_opt_sections.cfg") outfile = os.path.join( self._tempdir, - "surfdata_5x5_amazon_16pfts_Irrig_CMIP6_simyr2000_c171214_output_urban.nc", + "surfdata_5x5_amazon_hist_16pfts_CMIP6_2000_c231031_output_urban.nc", ) sys.argv = [ "fsurdat_modifier", self._cfg_file_path, "-i", os.path.join( - self._testinputs_path, "surfdata_5x5_amazon_16pfts_Irrig_CMIP6_simyr2000_c171214.nc" + self._testinputs_path, "surfdata_5x5_amazon_hist_16pfts_CMIP6_2000_c231031.nc" ), "-o", outfile, @@ -182,12 +182,9 @@ def test_opt_sections(self): lev2_two = np.empty((2, 3, 5, 5)) lev2_two[0, :, :, :] = 200.0 lev2_two[1, :, :, :] = 100.0 - lev2_five = np.empty((5, 3, 5, 5)) - lev2_five[0, :, :, :] = 1.0 - lev2_five[1, :, :, :] = 2.0 - lev2_five[2, :, :, :] = 3.0 - lev2_five[3, :, :, :] = 4.0 - lev2_five[4, :, :, :] = 5.0 + lev2_ten = np.empty((10, 3, 5, 5)) + for x in range(10): + lev2_ten[x, :, :, :] = float(x + 1) lev1 = np.array( [ [ @@ -217,12 +214,13 @@ def test_opt_sections(self): np.testing.assert_array_equal(fsurdat_out_data.PCT_CROP, zero0d) np.testing.assert_array_equal(fsurdat_out_data.PCT_LAKE, zero0d) np.testing.assert_array_equal(fsurdat_out_data.PCT_WETLAND, zero0d) + np.testing.assert_array_equal(fsurdat_out_data.PCT_OCEAN, zero0d) np.testing.assert_array_equal(fsurdat_out_data.PCT_GLACIER, zero0d) np.testing.assert_array_equal(fsurdat_out_data.PCT_URBAN, pct_urban) np.testing.assert_array_equal(fsurdat_out_data.LAKEDEPTH, one0d * 200.0) np.testing.assert_array_equal(fsurdat_out_data.T_BUILDING_MIN, lev1) np.testing.assert_array_equal(fsurdat_out_data.ALB_ROOF_DIR, lev2_two) - np.testing.assert_array_equal(fsurdat_out_data.TK_ROOF, lev2_five) + np.testing.assert_array_equal(fsurdat_out_data.TK_ROOF, lev2_ten) def test_evenly_split_cropland(self): """ @@ -257,15 +255,15 @@ def test_1x1_mexicocity(self): ) expectfile = os.path.join( self._testinputs_path, - "surfdata_1x1_mexicocityMEX_hist_16pfts_Irrig_CMIP6_simyr2000_c221206_modified.nc", + "surfdata_1x1_mexicocityMEX_hist_16pfts_CMIP6_2000_c231103_modified.nc", ) outfile = os.path.join( self._tempdir, - "surfdata_1x1_mexicocityMEX_hist_16pfts_Irrig_CMIP6_simyr2000_c221206_modified.nc", + "surfdata_1x1_mexicocityMEX_hist_16pfts_CMIP6_2000_c231103_modified.nc", ) infile = os.path.join( self._testinputs_path, - "surfdata_1x1_mexicocityMEX_hist_16pfts_Irrig_CMIP6_simyr2000_c221206.nc", + "surfdata_1x1_mexicocityMEX_hist_16pfts_CMIP6_2000_c231103.nc", ) sys.argv = [ "fsurdat_modifier", diff --git a/python/ctsm/test/test_sys_gen_mksurfdata_jobscript_multi.py b/python/ctsm/test/test_sys_gen_mksurfdata_jobscript_multi.py new file mode 100755 index 0000000000..6f6bd88553 --- /dev/null +++ b/python/ctsm/test/test_sys_gen_mksurfdata_jobscript_multi.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python3 + +"""System tests for gen_mksurfdata_jobscript_multi + +""" + +import os + +import unittest +import tempfile +import shutil +import sys + +from ctsm.path_utils import path_to_ctsm_root +from ctsm.toolchain.gen_mksurfdata_jobscript_multi import main +from ctsm import unit_testing + +# Allow test names that pylint doesn't like; otherwise hard to make them +# readable +# pylint: disable=invalid-name + + +class TestSysGenMkSurfJSMulti(unittest.TestCase): + """System tests for gen_mksurfdata_jobscript_multi""" + + def setUp(self): + """Setp temporary directory to make the files in""" + self._original_wd = os.getcwd() + self._tempdir = tempfile.mkdtemp() + os.chdir(self._tempdir) + self.outfile = "jobscript.sh" + bld_path = os.path.join( + path_to_ctsm_root(), "python", "ctsm", "test", "testinputs", "mksurfdata_esmf_bld" + ) + sys.argv = [ + "gen_mksurfdata_jobscript_multi", + "--bld-path", + bld_path, + "--jobscript-file", + self.outfile, + ] + + def tearDown(self): + """ + Remove temporary directory + """ + os.chdir(self._original_wd) + shutil.rmtree(self._tempdir, ignore_errors=True) + + def createJS(self, nodes, tasks_per_node, scenario, option_list=None): + """ + Create a JobScript by sending a list of options in + """ + if option_list is None: + option_list = [] + if len(option_list) > 1: + sys.argv.extend(option_list) + sys.argv.extend( + [ + "--number-of-nodes", + nodes, + "--tasks-per-node", + tasks_per_node, + "--scenario", + scenario, + ] + ) + main() + self.assertTrue(os.path.exists(self.outfile), "Output jobscript file should exist") + + def test_simple_jobscript_multi(self): + """ + Test that a standard simple namelist works + """ + # pylint: disable=no-self-use + self.createJS(nodes="4", tasks_per_node="12", scenario="crop-global-present") + + +if __name__ == "__main__": + unit_testing.setup_for_tests() + unittest.main() diff --git a/python/ctsm/test/test_sys_gen_mksurfdata_jobscript_single.py b/python/ctsm/test/test_sys_gen_mksurfdata_jobscript_single.py new file mode 100755 index 0000000000..fdcc97ffd1 --- /dev/null +++ b/python/ctsm/test/test_sys_gen_mksurfdata_jobscript_single.py @@ -0,0 +1,129 @@ +#!/usr/bin/env python3 + +"""System tests for gen_mksurfdata_jobscript_single + +""" + +import os + +import unittest +import tempfile +import shutil +import sys + +from ctsm.path_utils import path_to_ctsm_root +from ctsm.toolchain.gen_mksurfdata_jobscript_single import main +from ctsm import unit_testing + +# Allow test names that pylint doesn't like; otherwise hard to make them +# readable +# pylint: disable=invalid-name + + +class TestSysGenMkSurfJSSingle(unittest.TestCase): + """System tests for gen_mksurfdata_jobscript_single""" + + def setUp(self): + """Setp temporary directory to make the files in""" + self._original_wd = os.getcwd() + self._tempdir = tempfile.mkdtemp() + os.chdir(self._tempdir) + self.outfile = "jobscript.sh" + self.namelist = "res.namelist" + bld_path = os.path.join( + path_to_ctsm_root(), "python", "ctsm", "test", "testinputs", "mksurfdata_esmf_bld" + ) + sys.argv = [ + "gen_mksurfdata_jobscript_single", + "--bld-path", + bld_path, + "--namelist", + self.namelist, + "--jobscript-file", + self.outfile, + ] + + def tearDown(self): + """ + Remove temporary directory + """ + os.chdir(self._original_wd) + shutil.rmtree(self._tempdir, ignore_errors=True) + + def createJS(self, nodes, tasks_per_node, option_list=None): + """ + Create a JobScript by sending a list of options in + """ + if option_list is None: + option_list = [] + if len(option_list) > 1: + sys.argv.extend(option_list) + sys.argv.extend( + [ + "--number-of-nodes", + nodes, + "--tasks-per-node", + tasks_per_node, + ] + ) + print(sys.argv) + main() + self.assertTrue(os.path.exists(self.outfile), "Output jobscript file should exist") + + def test_simple_jobscript_single(self): + """ + Test that a standard simple namelist works + """ + # pylint: disable=no-self-use + self.createJS(nodes="4", tasks_per_node="12") + + def test_casper_jobscript_single(self): + """ + Test that a standard simple namelist works for casper + """ + # pylint: disable=no-self-use + opt_list = ["--machine", "casper"] + self.createJS(nodes="4", tasks_per_node="12", option_list=opt_list) + + def test_izumi_jobscript_single(self): + """ + Test that a standard simple namelist works for asper + """ + # pylint: disable=no-self-use + opt_list = ["--machine", "izumi"] + self.createJS(nodes="4", tasks_per_node="12", option_list=opt_list) + + def test_bad_bld_path(self): + """ + Test aborts if the input bld-path does NOT exist + """ + # pylint: disable=no-self-use + with self.assertRaisesRegex(SystemExit, "Input Build path"): + self.createJS(nodes="4", tasks_per_node="12", option_list=["--bld-path", "zztop"]) + + def test_neg_nodes(self): + """ + Test aborts if the input node count is negative + """ + # pylint: disable=no-self-use + with self.assertRaisesRegex( + SystemExit, + "Input argument --number_of_nodes is zero or negative and needs to be positive", + ): + self.createJS(nodes="-4", tasks_per_node="12") + + def test_neg_tasks(self): + """ + Test aborts if the input tasks_per_node is zero or negative + """ + # pylint: disable=no-self-use + with self.assertRaisesRegex( + SystemExit, + "Input argument --tasks_per_node is zero or negative and needs to be positive", + ): + self.createJS(nodes="4", tasks_per_node="0") + + +if __name__ == "__main__": + unit_testing.setup_for_tests() + unittest.main() diff --git a/python/ctsm/test/test_sys_gen_mksurfdata_namelist.py b/python/ctsm/test/test_sys_gen_mksurfdata_namelist.py new file mode 100755 index 0000000000..29745e9d80 --- /dev/null +++ b/python/ctsm/test/test_sys_gen_mksurfdata_namelist.py @@ -0,0 +1,152 @@ +#!/usr/bin/env python3 + +"""System tests for gen_mksurfdata_namelist + +""" + +import os + +import unittest +import tempfile +import shutil +import sys + +from ctsm.path_utils import path_to_ctsm_root +from ctsm.toolchain.gen_mksurfdata_namelist import main +from ctsm import unit_testing + +# Allow test names that pylint doesn't like; otherwise hard to make them +# readable +# pylint: disable=invalid-name + + +class TestSysGenMkSurfNML(unittest.TestCase): + """System tests for gen_mksurfdata_namelist""" + + def setUp(self): + """Setp temporary directory to make the files in""" + testinputs_path = os.path.join(path_to_ctsm_root(), "python/ctsm/test/testinputs") + self._testinputs_path = testinputs_path + self._original_wd = os.getcwd() + self._tempdir = tempfile.mkdtemp() + os.chdir(self._tempdir) + self.outfile = "surfdata.namelist" + sys.argv = [ + "gen_mksurfdata_namelist", + "--namelist", + self.outfile, + ] + + def tearDown(self): + """ + Remove temporary directory + """ + os.chdir(self._original_wd) + shutil.rmtree(self._tempdir, ignore_errors=True) + + def test_simple_namelist(self): + """ + Test that a standard simple namelist works + """ + # pylint: disable=no-self-use + sys.argv.extend( + [ + "--start-year", + "2000", + "--end-year", + "2000", + "--res", + "0.9x1.25", + ] + ) + main() + self.assertTrue(os.path.exists(self.outfile), "Output surface dataset file should exist") + + def test_vic_nocrop_inlandwet_glc_namelist(self): + """ + Test a namelist with several options on + """ + # pylint: disable=no-self-use + sys.argv.extend( + [ + "--start-year", + "1850", + "--end-year", + "1850", + "--res", + "1.9x2.5", + "--vic", + "--nocrop", + "--inlandwet", + "--glc", + ] + ) + main() + self.assertTrue(os.path.exists(self.outfile), "Output surface dataset file should exist") + + def test_hires_namelist(self): + """ + Test that a high resolution namelist works + """ + # pylint: disable=no-self-use + sys.argv.extend( + [ + "--start-year", + "1850", + "--end-year", + "1850", + "--res", + "mpasa15", + "--glc-nec", + "10", + "--hires_pft", + "--hires_soitex", + ] + ) + main() + self.assertTrue(os.path.exists(self.outfile), "Output surface dataset file should exist") + + def test_ssp_transient_namelist(self): + """ + Test that a SSP transient namelist works + """ + # pylint: disable=no-self-use + sys.argv.extend( + [ + "--start-year", + "1850", + "--end-year", + "2100", + "--res", + "ne30np4.pg3", + "--ssp-rcp", + "SSP2-4.5", + "--nosurfdata", + ] + ) + main() + self.assertTrue(os.path.exists(self.outfile), "Output surface dataset file should exist") + + def test_potveg_namelist(self): + """ + Test that a potential vegetation namelist works + """ + # pylint: disable=no-self-use + sys.argv.extend( + [ + "--start-year", + "1850", + "--end-year", + "1850", + "--res", + "4x5", + "--potveg_flag", + ] + ) + main() + self.assertTrue(os.path.exists(self.outfile), "Output surface dataset file should exist") + + +if __name__ == "__main__": + unit_testing.setup_for_tests() + unittest.main() diff --git a/python/ctsm/test/test_sys_lilac_build_ctsm.py b/python/ctsm/test/test_sys_lilac_build_ctsm.py index a8af9b2eab..57263e47da 100755 --- a/python/ctsm/test/test_sys_lilac_build_ctsm.py +++ b/python/ctsm/test/test_sys_lilac_build_ctsm.py @@ -42,8 +42,12 @@ def setUp(self): else: self._ncarhost = None + self._original_wd = os.getcwd() + os.chdir(self._tempdir) + def tearDown(self): - os.chdir(self._previous_dir) + """tear down""" + os.chdir(self._original_wd) shutil.rmtree(self._tempdir, ignore_errors=True) if self._ncarhost is not None: os.environ["NCAR_HOST"] = self._ncarhost diff --git a/python/ctsm/test/test_sys_mesh_modifier.py b/python/ctsm/test/test_sys_mesh_modifier.py index da59368391..f94c86e547 100755 --- a/python/ctsm/test/test_sys_mesh_modifier.py +++ b/python/ctsm/test/test_sys_mesh_modifier.py @@ -43,20 +43,21 @@ def setUp(self): self._cfg_template_path = os.path.join( path_to_ctsm_root(), "tools/modify_input_files/modify_mesh_template.cfg" ) - testinputs_path = os.path.join(path_to_ctsm_root(), "python/ctsm/test/testinputs") - fsurdat_in = os.path.join( - testinputs_path, - "surfdata_5x5_amazon_16pfts_Irrig_CMIP6_simyr2000_c171214.nc", - ) + self.testinputs_path = os.path.join(path_to_ctsm_root(), "python/ctsm/test/testinputs") self._tempdir = tempfile.mkdtemp() self._cfg_file_path = os.path.join(self._tempdir, "modify_mesh_mask.cfg") self._mesh_mask_in = os.path.join(self._tempdir, "mesh_mask_in.nc") self._mesh_mask_out = os.path.join(self._tempdir, "mesh_mask_out.nc") self._landmask_file = os.path.join(self._tempdir, "landmask.nc") - scrip_file = os.path.join(self._tempdir, "scrip.nc") - metadata_file = os.path.join(self._tempdir, "metadata.nc") + self.scrip_file = os.path.join(self._tempdir, "scrip.nc") + self.metadata_file = os.path.join(self._tempdir, "metadata.nc") configure_path = os.path.join(path_to_cime(), "CIME/scripts/configure") + self._lat_varname = None + self._lon_varname = None + self._lat_dimname = None + self._lon_dimname = None + self._previous_dir = os.getcwd() os.chdir(self._tempdir) # cd to tempdir @@ -67,21 +68,35 @@ def setUp(self): except subprocess.CalledProcessError as e: sys.exit(f"{e} ERROR using {configure_cmd}") + def createScripGridAndMask(self, fsurdat_in): + """Create the SCRIP grid and mask file""" # Generate scrip file from fsurdat_in using nco # In the ctsm_py environment this requires running 'module load nco' # interactively - ncks_cmd = f"ncks --rgr infer --rgr scrip={scrip_file} {fsurdat_in} {metadata_file}" + if os.path.exists(self.scrip_file): + os.remove(self.scrip_file) + # --rgr infer, means create the vertices bases on the cell centers (--rgr is the regrid options for ncks) + # --rgr scrip=, names the output SCRIP grid file + # The mask will be idnetically 1, no matter the input grid (you can, change it, but you have to get it from a mapping file) + # Since, the mask is going to be changed later, it's fine that the mask at this point is identically 1. + + # This could also alturnatively be done, by using the stored SCRIP grid file for the resolution under CESM inputdata + ncks_cmd = ( + f"ncks --rgr infer --rgr scrip={self.scrip_file} {fsurdat_in} {self.metadata_file}" + ) try: subprocess.check_call(ncks_cmd, shell=True) except subprocess.CalledProcessError as e: err_msg = ( - f"{e} ERROR using ncks to generate {scrip_file} from " + f"{e} ERROR using ncks to generate {self.scrip_file} from " + f"{fsurdat_in}; MOST LIKELY SHOULD INVOKE module load nco" ) sys.exit(err_msg) # Run .env_mach_specific.sh to load esmf and generate mesh_mask_in # Execute two commands at once to preserve the results of the first - two_commands = f". {self._tempdir}/.env_mach_specific.sh; ESMF_Scrip2Unstruct {scrip_file} {self._mesh_mask_in} 0" + if os.path.exists(self._mesh_mask_in): + os.remove(self._mesh_mask_in) + two_commands = f". {self._tempdir}/.env_mach_specific.sh; ESMF_Scrip2Unstruct {self.scrip_file} {self._mesh_mask_in} 0" try: subprocess.check_call(two_commands, shell=True) except subprocess.CalledProcessError as e: @@ -96,9 +111,13 @@ def setUp(self): self._lat_dimname = fsurdat_in_data[self._lat_varname].dims[0] self._lon_dimname = fsurdat_in_data[self._lat_varname].dims[1] + def createLandMaskFile(self, fsurdat_in): + """Create the LandMask file from the input fsurdat_in file""" + if os.path.exists(self._landmask_file): + os.remove(self._landmask_file) ncap2_cmd = ( - "ncap2 -A -v -s 'mod_lnd_props=PFTDATA_MASK' " - + "-A -v -s 'landmask=PFTDATA_MASK' " + "ncap2 -A -v -s 'mod_lnd_props=LANDFRAC_MKSURFDATA.convert(NC_INT)' " + + "-A -v -s 'landmask=LANDFRAC_MKSURFDATA.convert(NC_INT)' " + f"-A -v -s {self._lat_varname}={self._lat_varname} " + f"-A -v -s {self._lon_varname}={self._lon_varname} " + f"{fsurdat_in} {self._landmask_file}" @@ -119,16 +138,27 @@ def test_allInfo(self): """ This test specifies all the information that one may specify Create .cfg file, run the tool, compare mesh_mask_in to mesh_mask_out + For a case where the mesh remains unchanged, it's just output as + ocean so the mesh is output as all zero's rather than the all 1's that came in. """ + fsurdat_in = os.path.join( + self.testinputs_path, + "surfdata_5x5_amazon_hist_78pfts_CMIP6_2000_c230517.nc", + ) + self.createScripGridAndMask(fsurdat_in) + self.createLandMaskFile(fsurdat_in) self._create_config_file() # run the mesh_mask_modifier tool + if os.path.exists(self._mesh_mask_out): + os.remove(self._mesh_mask_out) mesh_mask_modifier(self._cfg_file_path) # the critical piece of this test is that the above command # doesn't generate errors; however, we also do some assertions below # Error checks + # Use the mesh file that was created with to compare to with a mask identical to 1 mesh_mask_in_data = xr.open_dataset(self._mesh_mask_in) mesh_mask_out_data = xr.open_dataset(self._mesh_mask_out) @@ -138,7 +168,47 @@ def test_allInfo(self): # the Mask variable will now equal zeros, not ones element_mask_in = mesh_mask_in_data.elementMask element_mask_out = mesh_mask_out_data.elementMask - self.assertTrue(element_mask_out.equals(element_mask_in - 1)) + self.assertTrue( + element_mask_out.equals(element_mask_in - 1) + ) # The -1 is because of the comment above about the mask + + def test_modifyMesh(self): + """ + This test specifies all the information that one may specify + Create .cfg file, run the tool, compare mesh_mask_in to mesh_mask_out + For a case where the mesh is changed. + """ + + fsurdat_in = os.path.join( + self.testinputs_path, + "surfdata_5x5_amazon_hist_78pfts_CMIP6_2000_c230517_modify_mask.nc", + ) + self.createScripGridAndMask(fsurdat_in) + self.createLandMaskFile(fsurdat_in) + self._create_config_file() + + if os.path.exists(self._mesh_mask_out): + os.remove(self._mesh_mask_out) + + # run the mesh_mask_modifier tool + mesh_mask_modifier(self._cfg_file_path) + # the critical piece of this test is that the above command + # doesn't generate errors; however, we also do some assertions below + mesh_compare = os.path.join( + self.testinputs_path, "5x5pt_amazon-modify_mask_ESMFmesh_c20230911.nc" + ) + + # Error checks + mesh_mask_in_data = xr.open_dataset(mesh_compare) + mesh_mask_out_data = xr.open_dataset(self._mesh_mask_out) + + center_coords_in = mesh_mask_in_data.centerCoords + center_coords_out = mesh_mask_out_data.centerCoords + self.assertTrue(center_coords_out.equals(center_coords_in)) + # the Mask variable will now equal the comparision file + element_mask_in = mesh_mask_in_data.elementMask + element_mask_out = mesh_mask_out_data.elementMask + self.assertTrue(element_mask_out.equals(element_mask_in)) def _create_config_file(self): """ diff --git a/python/ctsm/test/test_sys_regrid_ggcmi_shdates.py b/python/ctsm/test/test_sys_regrid_ggcmi_shdates.py index 9209ebfe78..178481cd53 100755 --- a/python/ctsm/test/test_sys_regrid_ggcmi_shdates.py +++ b/python/ctsm/test/test_sys_regrid_ggcmi_shdates.py @@ -52,7 +52,7 @@ def setUp(self): # What is the complete set of input arguments (including script name)? regrid_template_file = os.path.join( - testinputs_path, "surfdata_5x5_amazon_16pfts_Irrig_CMIP6_simyr2000_c171214.nc" + testinputs_path, "surfdata_5x5_amazon_hist_16pfts_CMIP6_2000_c231031.nc" ) self._function_call_list = [ "regrid_ggcmi_shdates", diff --git a/python/ctsm/test/test_unit_fsurdat_modifier.py b/python/ctsm/test/test_unit_fsurdat_modifier.py index bcb9099f61..2a6a8f455c 100755 --- a/python/ctsm/test/test_unit_fsurdat_modifier.py +++ b/python/ctsm/test/test_unit_fsurdat_modifier.py @@ -44,14 +44,10 @@ def setUp(self): self._testinputs_path = testinputs_path self._fsurdat_in = os.path.join( testinputs_path, - "surfdata_5x5_amazon_16pfts_Irrig_CMIP6_simyr2000_c171214.nc", + "surfdata_5x5_amazon_hist_16pfts_CMIP6_2000_c231031.nc", ) self._previous_dir = os.getcwd() self._tempdir = tempfile.mkdtemp() - self._fsurdat_in = os.path.join( - testinputs_path, - "surfdata_5x5_amazon_16pfts_Irrig_CMIP6_simyr2000_c171214.nc", - ) self._fsurdat_out = os.path.join(self._tempdir, "fsurdat_out.nc") sys.argv = [ "fsurdat_modifier", @@ -153,6 +149,7 @@ def test_read_subgrid_allglacier(self): self.config.set(section, "pct_urban", "0. 0. 0.") self.config.set(section, "pct_lake", "0.") self.config.set(section, "pct_wetland", "0.") + self.config.set(section, "pct_ocean", "0.") self.config.set(section, "pct_glacier", "100.") self.config.set(section, "pct_natveg", "0.") self.config.set(section, "pct_crop", "0.") @@ -166,6 +163,7 @@ def test_read_subgrid_allspecial(self): self.config.set(section, "pct_urban", "0. 0. 0.") self.config.set(section, "pct_lake", "25.") self.config.set(section, "pct_wetland", "35.") + self.config.set(section, "pct_ocean", "0.") self.config.set(section, "pct_glacier", "40.") self.config.set(section, "pct_natveg", "0.") self.config.set(section, "pct_crop", "0.") @@ -179,6 +177,7 @@ def test_read_subgrid_allurban(self): self.config.set(section, "pct_urban", "100.0 0.0 0.0") self.config.set(section, "pct_lake", "0.") self.config.set(section, "pct_wetland", "0.") + self.config.set(section, "pct_ocean", "0.") self.config.set(section, "pct_glacier", "0.") self.config.set(section, "pct_natveg", "0.") self.config.set(section, "pct_crop", "0.") @@ -256,6 +255,7 @@ def test_subgrid_notsumtohundred(self): self.config.set(section, "pct_urban", "0. 0. 0.") self.config.set(section, "pct_lake", "0.") self.config.set(section, "pct_wetland", "0.") + self.config.set(section, "pct_ocean", "0.") self.config.set(section, "pct_glacier", "0.") self.config.set(section, "pct_natveg", "0.") self.config.set(section, "pct_crop", "0.") diff --git a/python/ctsm/test/test_unit_gen_mksurfdata_jobscript_single.py b/python/ctsm/test/test_unit_gen_mksurfdata_jobscript_single.py new file mode 100755 index 0000000000..5038c6b3e1 --- /dev/null +++ b/python/ctsm/test/test_unit_gen_mksurfdata_jobscript_single.py @@ -0,0 +1,251 @@ +#!/usr/bin/env python3 + +""" +Unit tests for gen_mksurfdata_jobscript_single.py subroutines: +""" + +import unittest +import os +import sys +import shutil + +import tempfile + +from ctsm import unit_testing +from ctsm.path_utils import path_to_ctsm_root +from ctsm.path_utils import path_to_cime +from ctsm.os_utils import run_cmd_output_on_error +from ctsm.toolchain.gen_mksurfdata_jobscript_single import get_parser +from ctsm.toolchain.gen_mksurfdata_jobscript_single import get_mpirun +from ctsm.toolchain.gen_mksurfdata_jobscript_single import check_parser_args +from ctsm.toolchain.gen_mksurfdata_jobscript_single import write_runscript_part1 + + +def add_args(machine, nodes, tasks): + """add arguments to sys.argv""" + args_to_add = [ + "--machine", + machine, + "--number-of-nodes", + str(nodes), + "--tasks-per-node", + str(tasks), + ] + for item in args_to_add: + sys.argv.append(item) + + +def create_empty_file(filename): + """create an empty file""" + os.system("touch " + filename) + + +# Allow test names that pylint doesn't like; otherwise hard to make them +# readable +# pylint: disable=invalid-name + +# pylint: disable=protected-access +# pylint: disable=too-many-instance-attributes +class TestFGenMkSurfJobscriptSingle(unittest.TestCase): + """Tests the gen_mksurfdata_jobscript_single subroutines""" + + def setUp(self): + """Setup for trying out the methods""" + testinputs_path = os.path.join(path_to_ctsm_root(), "python/ctsm/test/testinputs") + self._testinputs_path = testinputs_path + self._previous_dir = os.getcwd() + self._tempdir = tempfile.mkdtemp() + os.chdir(self._tempdir) + self._account = "ACCOUNT_NUMBER" + self._jobscript_file = "output_jobscript" + self._output_compare = """#!/bin/bash +# Edit the batch directives for your batch system +# Below are default batch directives for derecho +#PBS -N mksurfdata +#PBS -j oe +#PBS -k eod +#PBS -S /bin/bash +#PBS -l walltime=12:00:00 +#PBS -A ACCOUNT_NUMBER +#PBS -q main +#PBS -l select=1:ncpus=128:mpiprocs=64:mem=218GB + +# This is a batch script to run a set of resolutions for mksurfdata_esmf input namelist +# NOTE: THIS SCRIPT IS AUTOMATICALLY GENERATED SO IN GENERAL YOU SHOULD NOT EDIT it!! + +""" + self._bld_path = os.path.join(self._tempdir, "tools_bld") + os.makedirs(self._bld_path) + self.assertTrue(os.path.isdir(self._bld_path)) + self._nlfile = os.path.join(self._tempdir, "namelist_file") + create_empty_file(self._nlfile) + self.assertTrue(os.path.exists(self._nlfile)) + self._mksurf_exe = os.path.join(self._bld_path, "mksurfdata") + create_empty_file(self._mksurf_exe) + self.assertTrue(os.path.exists(self._mksurf_exe)) + self._env_mach = os.path.join(self._bld_path, ".env_mach_specific.sh") + create_empty_file(self._env_mach) + self.assertTrue(os.path.exists(self._env_mach)) + sys.argv = [ + "gen_mksurfdata_jobscript_single", + "--bld-path", + self._bld_path, + "--namelist-file", + self._nlfile, + "--jobscript-file", + self._jobscript_file, + "--account", + self._account, + ] + + def tearDown(self): + """ + Remove temporary directory + """ + os.chdir(self._previous_dir) + shutil.rmtree(self._tempdir, ignore_errors=True) + + def assertFileContentsEqual(self, expected, filepath, msg=None): + """Asserts that the contents of the file given by 'filepath' are equal to + the string given by 'expected'. 'msg' gives an optional message to be + printed if the assertion fails. + + Copied from test_unit_job_launcher_no_batch should go to utils!""" + + with open(filepath, "r") as myfile: + contents = myfile.read() + + self.assertEqual(expected, contents, msg=msg) + + def test_simple_derecho_args(self): + """test simple derecho arguments""" + machine = "derecho" + nodes = 1 + tasks = 64 + add_args(machine, nodes, tasks) + args = get_parser().parse_args() + check_parser_args(args) + with open(self._jobscript_file, "w", encoding="utf-8") as runfile: + attribs = write_runscript_part1( + nodes, tasks, machine, self._account, args.walltime, runfile + ) + self.assertEqual({"mpilib": "default"}, attribs, msg="attribs not as expected") + + self.assertFileContentsEqual(self._output_compare, self._jobscript_file) + + def test_derecho_mpirun(self): + """ + test derecho mpirun. This would've helped caught a problem we ran into + It will also be helpful when externals are updated to guide to solutions + to problems + """ + machine = "derecho" + nodes = 4 + tasks = 128 + add_args(machine, nodes, tasks) + args = get_parser().parse_args() + check_parser_args(args) + self.assertEqual(machine, args.machine) + self.assertEqual(tasks, args.tasks_per_node) + self.assertEqual(nodes, args.number_of_nodes) + self.assertEqual(self._account, args.account) + # Create the env_mach_specific.xml file needed for get_mpirun + # This will catch problems with our usage of CIME objects + # Doing this here will also catch potential issues in the gen_mksurfdata_build script + configure_path = os.path.join(path_to_cime(), "CIME", "scripts", "configure") + self.assertTrue(os.path.exists(configure_path)) + options = " --macros-format CMake --silent --compiler intel --machine " + machine + cmd = configure_path + options + cmd_list = cmd.split() + run_cmd_output_on_error( + cmd=cmd_list, errmsg="Trouble running configure", cwd=self._bld_path + ) + self.assertTrue(os.path.exists(self._env_mach)) + expected_attribs = {"mpilib": "default"} + with open(self._jobscript_file, "w", encoding="utf-8") as runfile: + attribs = write_runscript_part1( + nodes, tasks, machine, self._account, args.walltime, runfile + ) + self.assertEqual(attribs, expected_attribs) + (executable, mksurfdata_path, env_mach_path) = get_mpirun(args, attribs) + expected_exe = "time mpibind " + self.assertEqual(executable, expected_exe) + self.assertEqual(mksurfdata_path, self._mksurf_exe) + self.assertEqual(env_mach_path, self._env_mach) + + def test_too_many_tasks(self): + """test trying to use too many tasks""" + machine = "derecho" + nodes = 1 + tasks = 129 + add_args(machine, nodes, tasks) + args = get_parser().parse_args() + check_parser_args(args) + with open(self._jobscript_file, "w", encoding="utf-8") as runfile: + with self.assertRaisesRegex( + SystemExit, + "Number of tasks per node exceeds the number of processors per node" + + " on this machine", + ): + write_runscript_part1(nodes, tasks, machine, self._account, args.walltime, runfile) + + def test_zero_tasks(self): + """test for fail on zero tasks""" + machine = "derecho" + nodes = 5 + tasks = 0 + add_args(machine, nodes, tasks) + args = get_parser().parse_args() + with self.assertRaisesRegex( + SystemExit, + "Input argument --tasks_per_node is zero or negative and needs to be positive", + ): + check_parser_args(args) + + def test_bld_build_path(self): + """test for bad build path""" + machine = "derecho" + nodes = 10 + tasks = 64 + add_args(machine, nodes, tasks) + # Remove the build path directory + shutil.rmtree(self._bld_path, ignore_errors=True) + args = get_parser().parse_args() + with self.assertRaisesRegex(SystemExit, "Input Build path .+ does NOT exist, aborting"): + check_parser_args(args) + + def test_mksurfdata_exist(self): + """test fails if mksurfdata does not exist""" + machine = "derecho" + nodes = 10 + tasks = 64 + add_args(machine, nodes, tasks) + args = get_parser().parse_args() + os.remove(self._mksurf_exe) + with self.assertRaisesRegex(SystemExit, "mksurfdata_esmf executable "): + check_parser_args(args) + + def test_env_mach_specific_exist(self): + """test fails if the .env_mach_specific.sh file does not exist""" + machine = "derecho" + nodes = 10 + tasks = 64 + add_args(machine, nodes, tasks) + args = get_parser().parse_args() + os.remove(self._env_mach) + with self.assertRaisesRegex(SystemExit, "Environment machine specific file"): + check_parser_args(args) + + def test_bad_machine(self): + """test bad machine name""" + machine = "zztop" + nodes = 1 + tasks = 64 + add_args(machine, nodes, tasks) + with self.assertRaises(SystemExit): + get_parser().parse_args() + + +if __name__ == "__main__": + unit_testing.setup_for_tests() + unittest.main() diff --git a/python/ctsm/test/test_unit_modify_fsurdat.py b/python/ctsm/test/test_unit_modify_fsurdat.py index a075035b73..b796cd940d 100755 --- a/python/ctsm/test/test_unit_modify_fsurdat.py +++ b/python/ctsm/test/test_unit_modify_fsurdat.py @@ -389,7 +389,9 @@ def test_check_varlist_lists_wrongsizes(self): lev1list = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0] settings = {"var_lev1": lev1list} with self.assertRaisesRegex( - SystemExit, "Variable var_lev1 is of the wrong size. It should be" + SystemExit, + " Variable var_lev1 is 8 is of the wrong size." + + " It should be = 9 in input settings dictionary", ): self.modify_fsurdat.check_varlist(settings) @@ -426,13 +428,17 @@ def test_check_varlist_uppercase(self): def test_check_varlist_badvar(self): """Test the check_varlist method for a variable not on the file""" settings = {"badvar": 100.0} - with self.assertRaisesRegex(SystemExit, "Variable badvar is NOT in the file"): + with self.assertRaisesRegex( + SystemExit, "Variable badvar is NOT in the input settings dictionary" + ): self.modify_fsurdat.check_varlist(settings) def test_check_varlist_badvar_uppercase(self): """Test the check_varlist method for a variable not on the file with allow uppercase""" settings = {"badvar": 100.0} - with self.assertRaisesRegex(SystemExit, "Variable BADVAR is NOT in the file"): + with self.assertRaisesRegex( + SystemExit, "Variable BADVAR is NOT in the input settings dictionary" + ): self.modify_fsurdat.check_varlist(settings, allow_uppercase_vars=True) def test_set_varlist_toohighdim(self): diff --git a/python/ctsm/test/test_unit_singlept_data_surfdata.py b/python/ctsm/test/test_unit_singlept_data_surfdata.py index 0052e796d1..d7fe3dc6c6 100755 --- a/python/ctsm/test/test_unit_singlept_data_surfdata.py +++ b/python/ctsm/test/test_unit_singlept_data_surfdata.py @@ -107,6 +107,12 @@ class TestSinglePointCaseSurfaceNoCrop(unittest.TestCase): coords={"lsmlat": lsmlat, "lsmlon": lsmlon}, attrs={"long_name": "percent wetland", "units": "unitless"}, ), + "PCT_OCEAN": xr.DataArray( + data=np.random.rand(1, 1), + dims=["lsmlat", "lsmlon"], + coords={"lsmlat": lsmlat, "lsmlon": lsmlon}, + attrs={"long_name": "percent ocean", "units": "unitless"}, + ), "PCT_URBAN": xr.DataArray( data=np.random.rand(1, 1, 3), dims=["lsmlat", "lsmlon", "numurbl"], @@ -672,6 +678,12 @@ class TestSinglePointCaseSurfaceCrop(unittest.TestCase): coords={"lsmlat": lsmlat, "lsmlon": lsmlon}, attrs={"long_name": "percent wetland", "units": "unitless"}, ), + "PCT_OCEAN": xr.DataArray( + data=np.random.rand(1, 1), + dims=["lsmlat", "lsmlon"], + coords={"lsmlat": lsmlat, "lsmlon": lsmlon}, + attrs={"long_name": "percent ocean", "units": "unitless"}, + ), "PCT_URBAN": xr.DataArray( data=np.random.rand(1, 1, 3), dims=["lsmlat", "lsmlon", "numurbl"], diff --git a/python/ctsm/test/test_unit_subset_data.py b/python/ctsm/test/test_unit_subset_data.py index b8ea5b06f2..1994a29102 100755 --- a/python/ctsm/test/test_unit_subset_data.py +++ b/python/ctsm/test/test_unit_subset_data.py @@ -31,7 +31,9 @@ class TestSubsetData(unittest.TestCase): def setUp(self): sys.argv = ["subset_data", "point", "--create-surface"] - DEFAULTS_FILE = os.path.join(os.getcwd(), "ctsm/test/testinputs/default_data.cfg") + DEFAULTS_FILE = os.path.join( + os.getcwd(), "../tools/site_and_regional/default_data_2000.cfg" + ) self.parser = get_parser() self.args = self.parser.parse_args() self.cesmroot = path_to_ctsm_root() @@ -46,7 +48,7 @@ def test_inputdata_setup_files_basic(self): files = setup_files(self.args, self.defaults, self.cesmroot) self.assertEqual( files["fsurf_in"], - "surfdata_0.9x1.25_hist_16pfts_Irrig_CMIP6_simyr2000_c190214.nc", + "surfdata_0.9x1.25_hist_2000_16pfts_c240216.nc", "fsurf_in filename not whats expected", ) self.assertEqual( @@ -134,7 +136,7 @@ def test_check_args_outsurfdat_fails_without_overwrite(self): outfile = os.path.join( os.getcwd(), "ctsm/test/testinputs/", - "surfdata_1x1_mexicocityMEX_hist_16pfts_Irrig_CMIP6_simyr2000_c221206.nc", + "surfdata_1x1_mexicocityMEX_hist_16pfts_CMIP6_2000_c231103.nc", ) self.assertTrue(os.path.exists(outfile), str(outfile) + " outfile should exist") diff --git a/python/ctsm/test/test_unit_utils_import_coord.py b/python/ctsm/test/test_unit_utils_import_coord.py index 11ff3c1b54..03e400f30f 100755 --- a/python/ctsm/test/test_unit_utils_import_coord.py +++ b/python/ctsm/test/test_unit_utils_import_coord.py @@ -49,7 +49,7 @@ def setUp(self): ) self._2d_lonlat_file = os.path.join( self._testinputs_path, - "surfdata_5x5_amazon_16pfts_Irrig_CMIP6_simyr2000_c171214_modified.nc", + "surfdata_5x5_amazon_hist_16pfts_CMIP6_2000_c231031_modified.nc", ) def tearDown(self): diff --git a/python/ctsm/test/testinputs/5x5pt_amazon-modify_mask_ESMFmesh_c20230911.nc b/python/ctsm/test/testinputs/5x5pt_amazon-modify_mask_ESMFmesh_c20230911.nc new file mode 100644 index 0000000000..67bb069848 --- /dev/null +++ b/python/ctsm/test/testinputs/5x5pt_amazon-modify_mask_ESMFmesh_c20230911.nc @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2909296cb8fc663974cb66f7a2101ab2ef9c98b72f180e4f4de030487f80f4ee +size 3236 diff --git a/python/ctsm/test/testinputs/mksurfdata_esmf_bld/.env_mach_specific.sh b/python/ctsm/test/testinputs/mksurfdata_esmf_bld/.env_mach_specific.sh new file mode 100644 index 0000000000..da0dc4f1bd --- /dev/null +++ b/python/ctsm/test/testinputs/mksurfdata_esmf_bld/.env_mach_specific.sh @@ -0,0 +1,17 @@ +# This file is for user convenience only and is not used by the model +# Changes to this file will be ignored and overwritten +# Changes to the environment should be made in env_mach_specific.xml +# Run ./case.setup --reset to regenerate this file +. /glade/u/apps/ch/opt/lmod/7.5.3/lmod/lmod/init/sh +module purge +module load ncarenv/1.3 python/3.7.9 cmake/3.22.0 intel/19.1.1 esmf_libs mkl +module use /glade/campaign/cesm/cesmdata/cseg/PROGS/modulefiles/esmfpkgs/intel/19.1.1/ +module load esmf-8.4.1b02-ncdfio-mpt-O mpt/2.25 netcdf-mpi/4.9.0 pnetcdf/1.12.3 ncarcompilers/0.5.0 pio/2.5.10 +export OMP_STACKSIZE=1024M +export TMPDIR=/glade/derecho/scratch/erik +export MPI_TYPE_DEPTH=16 +export MPI_USE_ARRAY=None +export COMPILER=intel +export MPILIB=mpt +export DEBUG=FALSE +export OS=LINUX diff --git a/python/ctsm/test/testinputs/mksurfdata_esmf_bld/env_mach_specific.xml b/python/ctsm/test/testinputs/mksurfdata_esmf_bld/env_mach_specific.xml new file mode 100644 index 0000000000..0284ee1952 --- /dev/null +++ b/python/ctsm/test/testinputs/mksurfdata_esmf_bld/env_mach_specific.xml @@ -0,0 +1,271 @@ + + +
+ These variables control the machine dependent environment including + the paths to compilers and libraries external to cime such as netcdf, + environment variables for use in the running job should also be set here. +
+ + + char + executable name + + + char + redirect for job output + + + + /glade/u/apps/ch/opt/lmod/7.5.3/lmod/lmod/init/perl + /glade/u/apps/ch/opt/lmod/7.5.3/lmod/lmod/init/env_modules_python.py + /glade/u/apps/ch/opt/lmod/7.5.3/lmod/lmod/init/csh + /glade/u/apps/ch/opt/lmod/7.5.3/lmod/lmod/init/sh + /glade/u/apps/ch/opt/lmod/7.5.3/lmod/lmod/libexec/lmod perl + /glade/u/apps/ch/opt/lmod/7.5.3/lmod/lmod/libexec/lmod python + module + module + + + ncarenv/1.3 + python/3.7.9 + cmake/3.22.0 + + + intel/19.1.1 + esmf_libs + mkl + + + gnu/10.1.0 + openblas/0.3.9 + + + pgi/20.4 + + + nvhpc/22.2 + + + /glade/campaign/cesm/cesmdata/cseg/PROGS/modulefiles/esmfpkgs/intel/19.1.1/ + esmf-8.4.1b02-ncdfio-mpt-g + + + /glade/campaign/cesm/cesmdata/cseg/PROGS/modulefiles/esmfpkgs/intel/19.1.1/ + esmf-8.4.1b02-ncdfio-mpt-O + + + /glade/campaign/cesm/cesmdata/cseg/PROGS/modulefiles/esmfpkgs/intel/19.1.1/ + esmf-8.4.1b02-ncdfio-openmpi-g + + + /glade/campaign/cesm/cesmdata/cseg/PROGS/modulefiles/esmfpkgs/intel/19.1.1/ + esmf-8.4.1b02-ncdfio-openmpi-O + + + mpi-serial/2.3.0 + + + /glade/campaign/cesm/cesmdata/cseg/PROGS/modulefiles/esmfpkgs/intel/19.1.1/ + esmf-8.4.1b02-ncdfio-mpiuni-g + + + /glade/campaign/cesm/cesmdata/cseg/PROGS/modulefiles/esmfpkgs/intel/19.1.1/ + esmf-8.4.1b02-ncdfio-mpiuni-O + + + /glade/campaign/cesm/cesmdata/cseg/PROGS/modulefiles/esmfpkgs/gnu/10.1.0/ + esmf-8.4.1b02-ncdfio-mpt-g + + + /glade/campaign/cesm/cesmdata/cseg/PROGS/modulefiles/esmfpkgs/gnu/10.1.0/ + esmf-8.4.1b02-ncdfio-mpt-O + + + /glade/campaign/cesm/cesmdata/cseg/PROGS/modulefiles/esmfpkgs/gnu/10.1.0/ + esmf-8.4.1b02-ncdfio-openmpi-g + + + /glade/campaign/cesm/cesmdata/cseg/PROGS/modulefiles/esmfpkgs/gnu/10.1.0/ + esmf-8.4.1b02-ncdfio-openmpi-O + + + /glade/campaign/cesm/cesmdata/cseg/PROGS/modulefiles/esmfpkgs/gnu/10.1.0/ + esmf-8.4.1b02-ncdfio-mpiuni-g + + + /glade/campaign/cesm/cesmdata/cseg/PROGS/modulefiles/esmfpkgs/gnu/10.1.0/ + esmf-8.4.1b02-ncdfio-mpiuni-O + + + /glade/campaign/cesm/cesmdata/cseg/PROGS/modulefiles/esmfpkgs/pgi/20.4/ + esmf-8.2.0b23-ncdfio-mpt-g + + + /glade/campaign/cesm/cesmdata/cseg/PROGS/modulefiles/esmfpkgs/pgi/20.4/ + esmf-8.2.0b23-ncdfio-mpt-O + + + /glade/campaign/cesm/cesmdata/cseg/PROGS/modulefiles/esmfpkgs/nvhpc/22.2 + esmf-8.4.1b02-ncdfio-mpt-O + + + /glade/campaign/cesm/cesmdata/cseg/PROGS/modulefiles/esmfpkgs/nvhpc/22.2 + esmf-8.4.1b02-ncdfio-mpt-g + + + /glade/campaign/cesm/cesmdata/cseg/PROGS/modulefiles/esmfpkgs/nvhpc/22.2 + esmf-8.4.1b02-ncdfio-openmpi-O + + + /glade/campaign/cesm/cesmdata/cseg/PROGS/modulefiles/esmfpkgs/nvhpc/22.2 + esmf-8.4.1b02-ncdfio-openmpi-g + + + /glade/campaign/cesm/cesmdata/cseg/PROGS/modulefiles/esmfpkgs/pgi/20.4/ + esmf-8.2.0b23-ncdfio-openmpi-g + + + /glade/campaign/cesm/cesmdata/cseg/PROGS/modulefiles/esmfpkgs/pgi/20.4/ + esmf-8.2.0b23-ncdfio-openmpi-O + + + /glade/campaign/cesm/cesmdata/cseg/PROGS/modulefiles/esmfpkgs/pgi/20.4/ + esmf-8.2.0b23-ncdfio-mpiuni-g + + + /glade/campaign/cesm/cesmdata/cseg/PROGS/modulefiles/esmfpkgs/pgi/20.4/ + esmf-8.2.0b23-ncdfio-mpiuni-O + + + /glade/campaign/cesm/cesmdata/cseg/PROGS/modulefiles/esmfpkgs/nvhpc/22.2 + esmf-8.4.1.b01-ncdfio-mpiuni-O + + + /glade/campaign/cesm/cesmdata/cseg/PROGS/modulefiles/esmfpkgs/nvhpc/22.2 + esmf-8.4.1b02-ncdfio-mpiuni-O + + + mpt/2.25 + netcdf-mpi/4.9.0 + pnetcdf/1.12.3 + + + mpt/2.25 + netcdf-mpi/4.9.0 + pnetcdf/1.12.3 + + + mpt/2.22 + netcdf-mpi/4.7.4 + pnetcdf/1.12.1 + + + mpt/2.25 + netcdf-mpi/4.9.0 + pnetcdf/1.12.3 + + + openmpi/4.1.4 + netcdf-mpi/4.9.0 + pnetcdf/1.12.3 + + + openmpi/4.1.4 + netcdf-mpi/4.9.0 + pnetcdf/1.12.3 + + + openmpi/4.0.5 + netcdf-mpi/4.7.4 + + + openmpi/4.1.4 + netcdf-mpi/4.9.0 + pnetcdf/1.12.3 + + + ncarcompilers/0.5.0 + + + netcdf/4.9.0 + + + netcdf/4.9.0 + + + netcdf/4.9.0 + + + netcdf/4.9.0 + + + pio/2.5.10 + + + pio/2.5.10d + + + + 1024M + /glade/derecho/scratch/$USER + 16 + + + + ON + SUMMARY + /glade/work/turuncu/FV3GFS/benchmark-inputs/2012010100/gfs/fcst + /glade/work/turuncu/FV3GFS/fix_am + /glade/work/turuncu/FV3GFS/addon + PASSIVE + true + + + false + + + /glade/derecho/scratch/$USER + + + -1 + + + mpiexec_mpt + + -p "%g:" + -np {{ total_tasks }} + omplace -tm open64 + + + + mpirun `hostname` + + -np {{ total_tasks }} + omplace -tm open64 + + + + mpiexec_mpt + + -p "%g:" + -np {{ total_tasks }} + omplace -tm open64 -vv + + + + mpirun `hostname` + + -np {{ total_tasks }} + + + + mpirun + + -np {{ total_tasks }} + --tag-output + + + + /opt/sgi/mpt/mpt-2.15/bin/mpirun $ENV{UNIT_TEST_HOST} -np 1 + +
diff --git a/python/ctsm/test/testinputs/mksurfdata_esmf_bld/mksurfdata b/python/ctsm/test/testinputs/mksurfdata_esmf_bld/mksurfdata new file mode 100755 index 0000000000..04909dbb93 --- /dev/null +++ b/python/ctsm/test/testinputs/mksurfdata_esmf_bld/mksurfdata @@ -0,0 +1,2 @@ +#!/bin/bash +# File to take the place of the mksurfdata_esmf executable for testing diff --git a/python/ctsm/test/testinputs/modify_fsurdat_1x1mexicocity.cfg b/python/ctsm/test/testinputs/modify_fsurdat_1x1mexicocity.cfg index 0d8a751f32..1190f003b2 100644 --- a/python/ctsm/test/testinputs/modify_fsurdat_1x1mexicocity.cfg +++ b/python/ctsm/test/testinputs/modify_fsurdat_1x1mexicocity.cfg @@ -37,6 +37,7 @@ PCT_NATVEG= 0.0 PCT_GLACIER= 0.0 PCT_WETLAND= 0.0 PCT_LAKE = 0.0 +PCT_OCEAN = 0.0 # Section with a list of variables to prcoess [modify_fsurdat_variable_list] @@ -71,13 +72,13 @@ ALB_ROOF_DIF = 0.2 0.2 ALB_WALL_DIR = 0.25 0.25 ALB_WALL_DIF = 0.25 0.25 -# Variabls on nlevurb which is 5 -TK_ROOF = 0.20 0.93 0.93 0.03 0.16 -TK_WALL = 0.88 0.88 0.88 0.88 0.88 -TK_IMPROAD = 0.82 0.82 2.10 2.10 2.10 -CV_ROOF = 1760000.0 1500000.0 1500000.0 250000.0 870000.0 -CV_WALL = 1540000.0 1540000.0 1540000.0 1540000.0 1540000.0 -CV_IMPROAD = 1740000.0 1740000.0 2000000.0 2000000.0 2000000.0 +# Variabls on nlevurb which is 10 +TK_ROOF = 0.20 0.93 0.93 0.03 0.16 0.20 0.93 0.93 0.03 0.16 +TK_WALL = 0.88 0.88 0.88 0.88 0.88 0.88 0.88 0.88 0.88 0.88 +TK_IMPROAD = 0.82 0.82 2.10 2.10 2.10 0.82 0.82 2.10 2.10 2.10 +CV_ROOF = 1760000.0 1500000.0 1500000.0 250000.0 870000.0 1760000.0 1500000.0 1500000.0 250000.0 870000.0 +CV_WALL = 1540000.0 1540000.0 1540000.0 1540000.0 1540000.0 1540000.0 1540000.0 1540000.0 1540000.0 1540000.0 +CV_IMPROAD = 1740000.0 1740000.0 2000000.0 2000000.0 2000000.0 1740000.0 1740000.0 2000000.0 2000000.0 2000000.0 # Natural and Crop PFT's don't really need to be set, since they have zero area, but # it looks better to do so diff --git a/python/ctsm/test/testinputs/modify_fsurdat_opt_sections.cfg b/python/ctsm/test/testinputs/modify_fsurdat_opt_sections.cfg index b1fcf8a2e1..36d7b50713 100644 --- a/python/ctsm/test/testinputs/modify_fsurdat_opt_sections.cfg +++ b/python/ctsm/test/testinputs/modify_fsurdat_opt_sections.cfg @@ -34,6 +34,7 @@ PCT_CROP = 0.0 PCT_LAKE = 0.0 PCT_GLACIER = 0.0 PCT_WETLAND = 0.0 +PCT_OCEAN = 0.0 # NOTE: PCT_URBAN must be a list of three floats that sum to the total urban area PCT_URBAN = 100.0 0.0 0.0 @@ -49,4 +50,4 @@ CANYON_HWR = 200.00 150.0 100. HT_ROOF = 200.0 150.0 100. T_BUILDING_MIN = 200 150.0 100. ALB_ROOF_DIR = 200. 100. -TK_ROOF = 1. 2. 3. 4. 5. +TK_ROOF = 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. diff --git a/python/ctsm/test/testinputs/modify_fsurdat_short.cfg b/python/ctsm/test/testinputs/modify_fsurdat_short.cfg index 38b88795e8..3a7f885c30 100644 --- a/python/ctsm/test/testinputs/modify_fsurdat_short.cfg +++ b/python/ctsm/test/testinputs/modify_fsurdat_short.cfg @@ -1,7 +1,7 @@ [modify_fsurdat_basic_options] -fsurdat_in = ctsm/test/testinputs/surfdata_5x5_amazon_16pfts_Irrig_CMIP6_simyr2000_c171214.nc -fsurdat_out = ctsm/test/testinputs/surfdata_5x5_amazon_16pfts_Irrig_CMIP6_simyr2000_c171214_out.nc +fsurdat_in = ctsm/test/testinputs/surfdata_5x5_amazon_hist_16pfts_CMIP6_2000_c231031.nc +fsurdat_out = ctsm/test/testinputs/surfdata_5x5_amazon_hist_16pfts_CMIP6_2000_c231031.out.nc idealized = False process_subgrid_section = False diff --git a/python/ctsm/test/testinputs/surfdata_1x1_mexicocityMEX_hist_16pfts_CMIP6_2000_c231103.nc b/python/ctsm/test/testinputs/surfdata_1x1_mexicocityMEX_hist_16pfts_CMIP6_2000_c231103.nc new file mode 100644 index 0000000000..ae21f4f6f8 --- /dev/null +++ b/python/ctsm/test/testinputs/surfdata_1x1_mexicocityMEX_hist_16pfts_CMIP6_2000_c231103.nc @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:eee6618ad3cb7893a12570895c8e85ac70de540bc569e801ead871d00193029e +size 27908 diff --git a/python/ctsm/test/testinputs/surfdata_1x1_mexicocityMEX_hist_16pfts_CMIP6_2000_c231103_modified.nc b/python/ctsm/test/testinputs/surfdata_1x1_mexicocityMEX_hist_16pfts_CMIP6_2000_c231103_modified.nc new file mode 100644 index 0000000000..d6091aa096 --- /dev/null +++ b/python/ctsm/test/testinputs/surfdata_1x1_mexicocityMEX_hist_16pfts_CMIP6_2000_c231103_modified.nc @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6ad9d750e176cbc19afa709dfd05557086254570d240fa801c2e9c8b600d2f12 +size 28332 diff --git a/python/ctsm/test/testinputs/surfdata_5x5_amazon_16pfts_Irrig_CMIP6_simyr2000_c171214.nc b/python/ctsm/test/testinputs/surfdata_5x5_amazon_16pfts_Irrig_CMIP6_simyr2000_c171214.nc deleted file mode 100644 index 56e5ed5fdd..0000000000 --- a/python/ctsm/test/testinputs/surfdata_5x5_amazon_16pfts_Irrig_CMIP6_simyr2000_c171214.nc +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:2b23addc0a7bdafaa5fc83368aa0939da02d2ad7a51e71cd5b4b78a3d440b2a5 -size 245144 diff --git a/python/ctsm/test/testinputs/surfdata_5x5_amazon_16pfts_Irrig_CMIP6_simyr2000_c171214_modified.nc b/python/ctsm/test/testinputs/surfdata_5x5_amazon_16pfts_Irrig_CMIP6_simyr2000_c171214_modified.nc deleted file mode 100644 index bb0a52a83f..0000000000 --- a/python/ctsm/test/testinputs/surfdata_5x5_amazon_16pfts_Irrig_CMIP6_simyr2000_c171214_modified.nc +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c05cb73bc232aa250bd9d752da986b58fee93ca1bb881a092d92b7e1752dd26f -size 247976 diff --git a/python/ctsm/test/testinputs/surfdata_5x5_amazon_16pfts_Irrig_CMIP6_simyr2000_c171214_modified_with_crop.nc b/python/ctsm/test/testinputs/surfdata_5x5_amazon_16pfts_Irrig_CMIP6_simyr2000_c171214_modified_with_crop.nc deleted file mode 100644 index 69f28b2239..0000000000 --- a/python/ctsm/test/testinputs/surfdata_5x5_amazon_16pfts_Irrig_CMIP6_simyr2000_c171214_modified_with_crop.nc +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0217926e5dea2f563a01ad7149be68cf6d0acb0a140715a5402fdf39a925b3e7 -size 247880 diff --git a/python/ctsm/test/testinputs/surfdata_5x5_amazon_hist_16pfts_CMIP6_2000_c231031.nc b/python/ctsm/test/testinputs/surfdata_5x5_amazon_hist_16pfts_CMIP6_2000_c231031.nc new file mode 100644 index 0000000000..54b7bef1b6 --- /dev/null +++ b/python/ctsm/test/testinputs/surfdata_5x5_amazon_hist_16pfts_CMIP6_2000_c231031.nc @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a0b39750baeb06add72002f0fc2540096b9876bb12d27a1c8d2ec2a5a11f83fd +size 260864 diff --git a/python/ctsm/test/testinputs/surfdata_5x5_amazon_hist_16pfts_CMIP6_2000_c231031_modified.nc b/python/ctsm/test/testinputs/surfdata_5x5_amazon_hist_16pfts_CMIP6_2000_c231031_modified.nc new file mode 100644 index 0000000000..d2de87f751 --- /dev/null +++ b/python/ctsm/test/testinputs/surfdata_5x5_amazon_hist_16pfts_CMIP6_2000_c231031_modified.nc @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dd3aa2c1400ee44e59132fc7dd3c1f62bb654810ac0c0d67f76f092f1a62a3de +size 259264 diff --git a/python/ctsm/test/testinputs/surfdata_5x5_amazon_hist_16pfts_CMIP6_2000_c231031_modified_with_crop.nc b/python/ctsm/test/testinputs/surfdata_5x5_amazon_hist_16pfts_CMIP6_2000_c231031_modified_with_crop.nc new file mode 100644 index 0000000000..3afe8b1803 --- /dev/null +++ b/python/ctsm/test/testinputs/surfdata_5x5_amazon_hist_16pfts_CMIP6_2000_c231031_modified_with_crop.nc @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5a7584a6344d482d5f047159d8bcc499575dcf87a1b6cd2014312f53245767d7 +size 259184 diff --git a/python/ctsm/test/testinputs/surfdata_5x5_amazon_hist_78pfts_CMIP6_2000_c230517.nc b/python/ctsm/test/testinputs/surfdata_5x5_amazon_hist_78pfts_CMIP6_2000_c230517.nc new file mode 100644 index 0000000000..f0b82db8c5 --- /dev/null +++ b/python/ctsm/test/testinputs/surfdata_5x5_amazon_hist_78pfts_CMIP6_2000_c230517.nc @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a3bd17959d5d72a5a7adcafc8e5ee3e5fb936f1a30cacbdbb0a1b02e1ffc5878 +size 893312 diff --git a/python/ctsm/test/testinputs/surfdata_5x5_amazon_hist_78pfts_CMIP6_2000_c230517_modified.nc b/python/ctsm/test/testinputs/surfdata_5x5_amazon_hist_78pfts_CMIP6_2000_c230517_modified.nc new file mode 100644 index 0000000000..f9746052a2 --- /dev/null +++ b/python/ctsm/test/testinputs/surfdata_5x5_amazon_hist_78pfts_CMIP6_2000_c230517_modified.nc @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3552caef9d6ea97d61f5ce765cfe9ab30f2d58d5fee4314b71f88f8c03fd1295 +size 891524 diff --git a/python/ctsm/test/testinputs/surfdata_5x5_amazon_hist_78pfts_CMIP6_2000_c230517_modified_with_crop.nc b/python/ctsm/test/testinputs/surfdata_5x5_amazon_hist_78pfts_CMIP6_2000_c230517_modified_with_crop.nc new file mode 100644 index 0000000000..b3e1860bc7 --- /dev/null +++ b/python/ctsm/test/testinputs/surfdata_5x5_amazon_hist_78pfts_CMIP6_2000_c230517_modified_with_crop.nc @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:93b0b528ef608b6762f3ee0e8b37d961adf2d83e91cf8552c9310bf5ef8e1743 +size 891444 diff --git a/python/ctsm/test/testinputs/surfdata_5x5_amazon_hist_78pfts_CMIP6_2000_c230517_modify_mask.nc b/python/ctsm/test/testinputs/surfdata_5x5_amazon_hist_78pfts_CMIP6_2000_c230517_modify_mask.nc new file mode 100644 index 0000000000..c07424cf50 --- /dev/null +++ b/python/ctsm/test/testinputs/surfdata_5x5_amazon_hist_78pfts_CMIP6_2000_c230517_modify_mask.nc @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:544478d315d2e994fc7b301aeb1b4825ebb6c60f2ef198c2d9c2cb13707f1d34 +size 893312 diff --git a/python/ctsm/toolchain/ctsm_case.py b/python/ctsm/toolchain/ctsm_case.py deleted file mode 100755 index 333af0833a..0000000000 --- a/python/ctsm/toolchain/ctsm_case.py +++ /dev/null @@ -1,427 +0,0 @@ -# 2020-11-08 Negin Sobhani -""" -This module includes the definition for CtsmCase class for the purpose of gen_mksurf_namelist. -""" - -# -- Import libraries -# -- Import Python Standard Libraries - -import os -import re -import sys -import logging - -from datetime import datetime - -from ctsm.git_utils import get_ctsm_git_describe - -# -- import local classes for this script -logger = logging.getLogger(__name__) - - -class CtsmCase: - """ - A class to encapsulate different ctsm cases. - - ... - - Attributes - --------- - res : str - resolution from a list of acceptable options. - glc_nec : str - number of glacier elevation classes. - ssp_rcp : str - Shared Socioeconomic Pathway and Representative - Concentration Pathway Scenario name. - crop_flag : bool - Crop flag for determining number of pfts - input_path : str - Raw data input path - vic_flag : bool - Flag for VIC model - glc_flag : bool - Flag for 3D glacier model - start_year : str - Simulation start year - end_year : str - Simulation end year - - Methods - ------- - check_endyear: - Check if end_year is bigger than start year - in a ctsm case. - check_run_type: - Determine if a ctsm case is transient or - time-slice. - check_num_pft: - Determine num_pft based on crop_flag for a - ctsm case. - build_landuse_filename: - Build the land-use filename for a transient - case. - create_landuse_file: - Create land-use txt file for a transient case. - build_namelist_filename - Build the name of the namelist/control file - for a ctsm case. - create_namelist_file: - Build the namelist/control file for a ctsm - case. - """ - - # pylint: disable=too-many-instance-attributes - - def __init__( - self, - res, - glc_nec, - ssp_rcp, - crop_flag, - input_path, - vic_flag, - glc_flag, - start_year, - end_year, - hres_flag, - ): - self.res = res - self.glc_nec = glc_nec - self.ssp_rcp = ssp_rcp - self.crop_flag = crop_flag - self.input_path = input_path - self.vic_flag = vic_flag - self.glc_flag = glc_flag - self.start_year = start_year - self.end_year = end_year - self.hres_flag = hres_flag - self.lu_fname = None - self.namelist_fname = None - self.ssp_val = None - self.rcp_val = None - - # -- check if end year value is a valid value - self.check_endyear() - - # -- Determine if the case is transient - self.check_run_type() - - # -- determine the num_pft - self.check_num_pft() - - def __str__(self): - return ( - str(self.__class__) - + "\n" - + "\n".join((str(key) + " = " + str(value) for key, value in self.__dict__.items())) - ) - - def check_endyear(self): - """ - check if end_year is valid. - - Raises: - Error is end_year is smaller than start_year - """ - if self.end_year < self.start_year: - sys.exit( - "ERROR: end_year should be bigger than the start_year : " - + self.start_year.__str__() - + "." - ) - - def check_run_type(self): - """ - Determine if a ctsm case is transient or - time-slice. - """ - if self.end_year > self.start_year: - self.run_type = "transient" - else: - self.run_type = "timeslice" - logger.debug(" run_type = %s", self.run_type) - - def check_num_pft(self): - """ - determine the num_pft - """ - if self.crop_flag: - self.num_pft = "78" - else: - self.num_pft = "16" - logger.debug(" crop_flag = %s => num_pft = %i", self.crop_flag.__str__(), self.num_pft) - - def build_landuse_filename(self): - """ - Build the land-use filename for a transient - case. - """ - if self.run_type == "transient": - lu_fname = ( - "landuse_timeseries_hist_" - + self.num_pft.__str__() - + "pfts_simyr" - + self.start_year.__str__() - + "-" - + self.end_year.__str__() - + ".txt" - ) - else: - lu_fname = "" - self.lu_fname = lu_fname - - def create_landuse_file(self): - """ - Create land-use txt file for a transient case. - """ - self.build_landuse_filename() - with open(self.lu_fname, "w", encoding="utf-8") as lu_file: - - for year in range(self.start_year, self.end_year + 1): - - # -- choose different files for years of 850-1850: - if 849 < year < 1850: - lu_input_fname = os.path.join( - self.input_path, - "pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012", - "mksrf_landuse_histclm50_LUH2_" + str(year) + ".c171012.nc", - ) - elif 1849 < year < 2016: - lu_input_fname = os.path.join( - self.input_path, - "pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412", - "mksrf_landuse_histclm50_LUH2_" + str(year) + ".c170412.nc", - ) - elif 2015 < year < 2106: - self.decode_ssp_rcp() - lu_input_fname = os.path.join( - self.input_path, - "pftcftdynharv.0.25x0.25." + self.ssp_rcp + ".simyr2016-2100.c181217", - "mksrf_landuse_SSP" - + self.ssp_val - + "RCP" - + self.rcp_val - + "_clm5_" - + str(year) - + ".c181217.nc", - ) - else: - logger.warning("year: %i not valid.", year) - - # -- Check if the land-use input file exist: - if not os.path.isfile(lu_input_fname): - logger.debug("lu_input_fname: %s", lu_input_fname) - logger.warning("land-use input file does not exist for year: %i.", year) - - # TODO: make the space/tab exactly the same as pl code: - lu_line = lu_input_fname + "\t\t\t" + str(year) + "\n" - - # -- Each line is written twice in the original pl code: - lu_file.write(lu_line) - lu_file.write(lu_line) - - logger.debug("year : %s", year) - logger.debug(lu_line) - - print("Successfully created land use file : ", self.lu_fname, ".") - print("-------------------------------------------------------") - - def build_namelist_filename(self): - """ - Build namelist file name. - """ - time_stamp = datetime.today().strftime("%y%m%d") - namelist_fname = ( - "surfdata_" - + self.res - + "_" - + self.ssp_rcp - + "_" - + self.num_pft - + "pfts_CMIP6_" - + self.start_year.__str__() - + "-" - + self.end_year.__str__() - + "_c" - + time_stamp - + ".namelist" - ) - - self.namelist_fname = namelist_fname - - def create_namelist_file(self): - """ - Build the namelist/control file for a ctsm case. - """ - - self.build_landuse_filename() - if self.run_type == "transient": - self.create_landuse_file() - - self.build_namelist_filename() - with open(self.namelist_fname, "w", encoding="utf-8") as namelist_file: - - label = get_ctsm_git_describe() - - dst_mesh = which_mesh(self.res) - - logger.debug("dst mesh is : %s", dst_mesh) - - if self.run_type == "transient": - use_transient = ".true." - else: - use_transient = ".false" - - # pylint: disable=line-too-long - - nl_template = ( - "&clmexp\n" - "nglcec = " + self.glc_nec + "\n" - "mksrf_fsoitex = " + self.input_path + "mksrf_soitex.10level.c201018.nc" + "\n" - "mksrf_forganic = " - + self.input_path - + "mksrf_organic_10level_5x5min_ISRIC-WISE-NCSCD_nlev7_c120830.nc" - + "\n" - "mksrf_flakwat = " - + self.input_path - + "mksrf_LakePnDepth_3x3min_simyr2004_csplk_c151015.nc" - + "\n" - "mksrf_fwetlnd = " + self.input_path + "mksrf_lanwat.050425.nc" + "\n" - "mksrf_fmax = " + self.input_path + "mksrf_fmax_3x3min_USGS_c120911.nc" + "\n" - "mksrf_fglacier = " - + self.input_path - + "mksrf_glacier_3x3min_simyr2000.c120926.nc" - + "\n" - "mksrf_fvocef = " - + self.input_path - + "mksrf_vocef_0.5x0.5_simyr2000.c110531.nc" - + "\n" - "mksrf_furbtopo = " + self.input_path + "mksrf_topo.10min.c080912.nc" + "\n" - "mksrf_fgdp = " - + self.input_path - + "mksrf_gdp_0.5x0.5_AVHRR_simyr2000.c130228.nc" - + "\n" - "mksrf_fpeat = " - + self.input_path - + "mksrf_peatf_0.5x0.5_AVHRR_simyr2000.c130228.nc" - + "\n" - "mksrf_fsoildepth = " - + self.input_path - + "mksf_soilthk_5x5min_ORNL-Soil_simyr1900-2015_c170630.nc" - + "\n" - "mksrf_fabm = " - + self.input_path - + "mksrf_abm_0.5x0.5_AVHRR_simyr2000.c130201.nc" - + "\n" - "outnc_double = .true. \n" - "all_urban = .false.\n" - "no_inlandwet = .true. \n" - "mksrf_furban = " - + self.input_path - + "mksrf_urban_0.05x0.05_simyr2000.c170724.nc" - + "\n" - "gitdescribe = " + label + "\n" - "mksrf_ftopostats = " - + self.input_path - + "mksrf_topostats_1km-merge-10min_HYDRO1K-merge-nomask_simyr2000.c130402.nc" - + "\n" - "mksrf_fvegtyp = " - + self.input_path - + "pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1850.c170629.nc" - + "\n" - "mksrf_fsoicol = " - + self.input_path - + "pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_soilcolor_CMIP6_simyr2005.c170623.nc" - + "\n" - "mksrf_flai = " - + self.input_path - + "pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_lai_78pfts_simyr2005.c170413.nc" - + "\n" - "fdyndat = ''\n" - "numpft = " + self.num_pft + "\n" - "dst_mesh_file = " + self.input_path + dst_mesh + "\n" - "\n&transient\n" - "use_transient = " + use_transient + "\n" - "start_year = " + self.start_year.__str__() + "\n" - "end_year = " + self.end_year.__str__() + "\n" - "mksrf_dyn_lu = " - + self.input_path - + "pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629" - + "\n" - "mksrf_fdynuse = " + self.lu_fname + "\n" - "\n&vic\n" - "use_vic = " + self.vic_flag.__str__() + "\n" - "mksrf_fvic = " - + self.input_path - + "mksrf_vic_0.9x1.25_GRDC_simyr2000.c130307.nc\n" - "outnc_vic = \n" - "\n&glc\n" - "use_glc = " + self.glc_flag.__str__() + "\n" - "outnc_3dglc = \n" - "/\n" - ) - # pylint: enable=line-too-long - - namelist_file.write(nl_template) - - print("Successfully created namelist file : ", self.namelist_fname, ".") - print("--------------------------------------------------------") - - def decode_ssp_rcp(self): - """ - Decode ssp_rcp strings because - the raw filenames and folder names - are not consistent. - - For example: - folder names have ssp_rcp as SSP1-2.6 - - but the files in these folders have - ssp_rcp as SSP1RCP26 - """ - - if self.ssp_rcp != "hist": - temp = re.sub("[^0-9]", "", self.ssp_rcp) - self.ssp_val = temp[0] - self.rcp_val = temp[1:] - else: - sys.exit( - "ERROR: \n" - + "\t Please choose a ssp_rcp scenario for years beyond 2015 using --ssp_rcp flag." - ) - - -def which_mesh(res): - """ - Figure out the dst mesh file for each res - """ - switcher = { - "512x1024": "lnd/clm2/mappingdata/grids/SCRIPgrid_512x1024_nomask_c110308.nc", - "128x256": "lnd/clm2/mappingdata/grids/SCRIPgrid_128x256_nomask_c110308.nc", - "94x192": "lnd/clm2/mappingdata/grids/SCRIPgrid_94x192_nomask_c110308.nc", - "64x128": "lnd/clm2/mappingdata/grids/SCRIPgrid_64x128_nomask_c110308.nc", - "48x96": "lnd/clm2/mappingdata/grids/SCRIPgrid_48x96_nomask_c110308.nc", - "32x64": "lnd/clm2/mappingdata/grids/SCRIPgrid_32x64_nomask_c110308.nc", - "8x16": "lnd/clm2/mappingdata/grids/SCRIPgrid_8x16_nomask_c110308.nc", - "0.23x0.31": "lnd/clm2/mappingdata/grids/SCRIPgrid_0.23x0.31_nomask_c110308.nc", - "0.47x0.63": "lnd/clm2/mappingdata/grids/SCRIPgrid_0.47x0.63_nomask_c170914.nc", - "0.9x1.25": "lnd/clm2/mappingdata/grids/0.9x1.25_c110307.nc", - "1.9x2.5": "lnd/clm2/mappingdata/grids/1.9x2.5_c110308.nc", - "2.5x3.33": "lnd/clm2/mappingdata/grids/SCRIPgrid_2.5x3.33_nomask_c110308.nc", - "4x5": "lnd/clm2/mappingdata/grids/SCRIPgrid_4x5_nomask_c110308.nc", - "10x15": "lnd/clm2/mappingdata/grids/SCRIPgrid_10x15_nomask_c110308.nc", - "C384": "atm/cam/coords/C384_SCRIP_desc.181018.nc", - "C192": "atm/cam/coords/C192_SCRIP_desc.181018.nc", - "C96": "atm/cam/coords/C96_SCRIP_desc.181018.nc", - "C48": "atm/cam/coords/C48_SCRIP_desc.181018.nc", - "C24": "atm/cam/coords/C24_SCRIP_desc.181018.nc", - "ne240np4": "lnd/clm2/mappingdata/grids/SCRIPgrid_ne240np4_nomask_c091227.nc", - "ne120np4": "lnd/clm2/mappingdata/grids/SCRIPgrid_ne120np4_nomask_c101123.nc", - "ne60np4": "lnd/clm2/mappingdata/grids/SCRIPgrid_ne60np4_nomask_c100408.nc", - "ne30np4": "lnd/clm2/mappingdata/grids/SCRIPgrid_ne30np4_nomask_c101123.nc", - "ne16np4": "lnd/clm2/mappingdata/grids/SCRIPgrid_ne16np4_nomask_c110512.nc", - "360x720cru": "lnd/clm2/mappingdata/grids/SCRIPgrid_360x720_nomask_c120830.nc", - } - - return switcher.get(res, "nothing") diff --git a/python/ctsm/toolchain/gen_mksurfdata_jobscript_multi.py b/python/ctsm/toolchain/gen_mksurfdata_jobscript_multi.py new file mode 100755 index 0000000000..6deb50ebfb --- /dev/null +++ b/python/ctsm/toolchain/gen_mksurfdata_jobscript_multi.py @@ -0,0 +1,398 @@ +""" +gen_mksurfdata_jobscript_multi.py generates a jobscript for running the +mksurfdata executable to generate many fsurdat files at once. For detailed +instructions, see README. +""" +import os +import sys +import logging + +from ctsm.utils import abort +from ctsm.toolchain.gen_mksurfdata_namelist import main as main_nml +from ctsm.ctsm_logging import process_logging_args +from ctsm.toolchain.gen_mksurfdata_jobscript_single import base_get_parser +from ctsm.toolchain.gen_mksurfdata_jobscript_single import check_parser_args +from ctsm.toolchain.gen_mksurfdata_jobscript_single import write_runscript_part1 +from ctsm.toolchain.gen_mksurfdata_jobscript_single import get_mpirun + + +logger = logging.getLogger(__name__) + +valid_scenarios = [ + "global-potveg", + "global-present", + "global-present-low-res", + "global-present-ultra-hi-res", + "crop-tropics-present", + "crop", + "crop-global-present", + "crop-global-present-low-res", + "crop-global-present-ne16", + "crop-global-present-ne30", + "crop-global-present-ne120", + "crop-global-present-mpasa480", + "crop-global-present-nldas", + "crop-global-1850", + "crop-global-1850-low-res", + "crop-global-1850-ne16", + "crop-global-1850-ne30", + "crop-global-1850-ne120", + "crop-global-1850-mpasa480", + "crop-global-hist", + "crop-global-hist-low-res", + "crop-global-hist-ne16", + "crop-global-hist-ne30", + "crop-global-SSP1-1.9-f09", + "crop-global-SSP1-2.6-f09", + "crop-global-SSP2-4.5-f09", + "crop-global-SSP2-4.5-f19", + "crop-global-SSP2-4.5-f10", + "crop-global-SSP2-4.5-f45", + "crop-global-SSP2-4.5-ne3", + "crop-global-SSP2-4.5-ne16", + "crop-global-SSP2-4.5-ne30", + "crop-global-SSP2-4.5-hcru", + "crop-global-SSP2-4.5-C96", + "crop-global-SSP2-4.5-mpasa120", + "crop-global-SSP3-7.0-f09", + "crop-global-SSP4-3.4-f09", + "crop-global-SSP4-6.0-f09", + "crop-global-SSP5-3.4-f09", + "crop-global-SSP5-8.5-f09", +] + + +def get_parser(): + """ + Get parser object for this script. + """ + parser = base_get_parser(default_js_name="mksurfdata_jobscript_multi.sh") + + parser.add_argument( + "--scenario", + help="""scenario""", + choices=valid_scenarios, + action="store", + dest="scenario", + required=True, + ) + + return parser + + +def write_runscript( + args, + scenario, + jobscript_file, + number_of_nodes, + tasks_per_node, + account, + walltime, + machine, + target_list, + resolution_dict, + dataset_dict, + runfile, +): + """ + Write run script + """ + # -------------------------- + # Write batch header (part 1) + # -------------------------- + name = f"mksrf_{scenario}" + attribs = write_runscript_part1( + number_of_nodes, + tasks_per_node, + machine, + account, + walltime, + runfile, + descrip=scenario, + name=name, + ) + # -------------------------- + # Obtain mpirun command from env_mach_specific.xml + # -------------------------- + (executable, mksurfdata_path, env_mach_path) = get_mpirun(args, attribs) + + # Run env_mach_specific.sh to control the machine dependent + # environment including the paths to compilers and libraries + # external to cime such as netcdf + runfile.write(". " + env_mach_path + "\n") + check = "if [ $? != 0 ]; then echo 'Error running env_specific_script'; exit -4; fi" + runfile.write(f"{check} \n") + for target in target_list: + res_set = dataset_dict[target][1] + if res_set not in resolution_dict: + abort(f"Resolution is not in the resolution_dict: {res_set}") + for res in resolution_dict[res_set]: + namelist = f"{scenario}_{res}.namelist" + command = os.path.join(os.getcwd(), "gen_mksurfdata_namelist") + command = command + " " + dataset_dict[target][0] + " " + res + command = command + " --silent" + command = command + f" --namelist {namelist}" + print(f"command is {command}") + sys.argv = [x for x in command.split(" ") if x] + main_nml() + print(f"generated namelist {namelist}") + output = f"{executable} {mksurfdata_path} < {namelist}" + runfile.write(f"{output} \n") + check = f"if [ $? != 0 ]; then echo 'Error running resolution {res}'; exit -4; fi" + runfile.write(f"{check} \n") + runfile.write(f"echo Successfully ran resolution {res}\n") + + runfile.write(f"echo Successfully ran {jobscript_file}\n") + + +def main(): + """ + See docstring at the top. + """ + # -------------------------- + # Obtain input args + # -------------------------- + args = get_parser().parse_args() + process_logging_args(args) + check_parser_args(args) + scenario = args.scenario + jobscript_file = args.jobscript_file + number_of_nodes = args.number_of_nodes + tasks_per_node = args.tasks_per_node + account = args.account + walltime = args.walltime + + # -------------------------- + # Determine target list + # -------------------------- + target_list = [scenario] + + # -------------------------- + # Error checking + # -------------------------- + for scenario_list in target_list: + if scenario_list not in valid_scenarios: + abort("Input scenario is NOT in valid_scenarios") + # -------------------------- + # Determine resolution sets that are referenced in commands + # TODO slevis: When new resolutions become supported in ccs_config, the + # first entry will change to + # "standard_res_no_crop": [ + # "0.9x1.25", + # "1.9x2.5", + # "mpasa60", + # "mpasa60-3conus", + # "mpasa60-3centralUS", + # ], + # -------------------------- + resolution_dict = { + "standard_res_no_crop": ["0.9x1.25", "1.9x2.5", "mpasa60"], + "f09": ["0.9x1.25"], + "f19": ["1.9x2.5"], + "hcru": ["360x720cru"], + "C96": ["C96"], + "mpasa120": ["mpasa120"], + "f10": ["10x15"], + "f45": ["4x5"], + "low_res_no_crop": ["4x5", "10x15"], + "ultra_hi_res_no_crop": ["mpasa15", "mpasa3p75"], + "standard_res": ["360x720cru", "0.9x1.25", "1.9x2.5", "C96", "mpasa120"], + "low_res": ["4x5", "10x15", "ne3np4.pg3"], + "mpasa480": ["mpasa480"], + "nldas_res": ["0.125nldas2"], + "5x5_amazon": ["5x5_amazon"], + "ne3": ["ne3np4.pg3"], + "ne16": ["ne16np4.pg3"], + "ne30": ["ne30np4.pg3", "ne30np4.pg2", "ne30np4"], + "ne120": [ + "ne0np4.ARCTICGRIS.ne30x8", + "ne0np4.ARCTIC.ne30x4", + "ne0np4CONUS.ne30x8", + "ne120np4.pg3", + ], + } + + # -------------------------- + # Determine commands for each target list + # -------------------------- + dataset_dict = { + "global-potveg": ( + "--start-year 1850 --end-year 1850 --nocrop --potveg --res", + "f09", + ), + "global-present": ( + "--start-year 2000 --end-year 2000 --nocrop --res", + "standard_res_no_crop", + ), + "global-present-low-res": ( + "--start-year 2000 --end-year 2000 --nocrop --res", + "low_res_no_crop", + ), + "global-present-ultra-hi-res": ( + "--start-year 2000 --end-year 2000 --nocrop --res", + "ultra_hi_res_no_crop", + ), + "crop-tropics-present": ( + "--start-year 2000 --end-year 2000 --res", + "5x5_amazon", + ), + "crop-global-present": ( + "--start-year 2000 --end-year 2000 --vic --res", + "standard_res", + ), + "crop-global-present-low-res": ( + "--start-year 2000 --end-year 2000 --vic --res", + "low_res", + ), + "crop-global-present-ne16": ( + "--start-year 2000 --end-year 2000 --res", + "ne16", + ), + "crop-global-present-ne30": ( + "--start-year 2000 --end-year 2000 --res", + "ne30", + ), + "crop-global-present-ne120": ( + "--start-year 2000 --end-year 2000 --res", + "ne120", + ), + "crop-global-present-mpasa480": ( + "--start-year 2000 --end-year 2000 --res", + "mpasa480", + ), + "crop-global-present-nldas": ( + # TODO slevis: --hirespft uses old data for now, so keep out + "--start-year 2000 --end-year 2000 --res", + "nldas_res", + ), + "crop-global-1850": ( + "--start-year 1850 --end-year 1850 --res", + "standard_res", + ), + "crop-global-1850-low-res": ( + "--start-year 1850 --end-year 1850 --res", + "low_res", + ), + "crop-global-1850-ne16": ( + "--start-year 1850 --end-year 1850 --res", + "ne16", + ), + "crop-global-1850-ne30": ( + "--start-year 1850 --end-year 1850 --res", + "ne30", + ), + "crop-global-1850-ne120": ( + "--start-year 1850 --end-year 1850 --res", + "ne120", + ), + "crop-global-1850-mpasa480": ( + "--start-year 1850 --end-year 1850 --res", + "mpasa480", + ), + "crop-global-hist": ( + "--start-year 1850 --end-year 2015 --nosurfdata --res", + "standard_res", + ), + "crop-global-hist-low-res": ( + "--start-year 1850 --end-year 2015 --nosurfdata --res", + "low_res", + ), + "crop-global-hist-ne16": ( + "--start-year 1850 --end-year 2015 --nosurfdata --res", + "ne16", + ), + "crop-global-hist-ne30": ( + "--start-year 1850 --end-year 2015 --nosurfdata --res", + "ne30", + ), + "crop-global-SSP1-1.9-f09": ( + "--start-year 1850 --end-year 2100 --nosurfdata --ssp-rcp SSP1-1.9 --res", + "f09", + ), + "crop-global-SSP1-2.6-f09": ( + "--start-year 1850 --end-year 2100 --nosurfdata --ssp-rcp SSP1-2.6 --res", + "f09", + ), + "crop-global-SSP2-4.5-f09": ( + "--start-year 1850 --end-year 2100 --nosurfdata --ssp-rcp SSP2-4.5 --res", + "f09", + ), + "crop-global-SSP2-4.5-hcru": ( + "--start-year 1850 --end-year 2100 --nosurfdata --ssp-rcp SSP2-4.5 --res", + "hcru", + ), + "crop-global-SSP2-4.5-f19": ( + "--start-year 1850 --end-year 2100 --nosurfdata --ssp-rcp SSP2-4.5 --res", + "f19", + ), + "crop-global-SSP2-4.5-f10": ( + "--start-year 1850 --end-year 2100 --nosurfdata --ssp-rcp SSP2-4.5 --res", + "f10", + ), + "crop-global-SSP2-4.5-f45": ( + "--start-year 1850 --end-year 2100 --nosurfdata --ssp-rcp SSP2-4.5 --res", + "f45", + ), + "crop-global-SSP2-4.5-ne3": ( + "--start-year 1850 --end-year 2100 --nosurfdata --ssp-rcp SSP2-4.5 --res", + "ne3", + ), + "crop-global-SSP2-4.5-ne30": ( + "--start-year 1850 --end-year 2100 --nosurfdata --ssp-rcp SSP2-4.5 --res", + "ne30", + ), + "crop-global-SSP2-4.5-ne16": ( + "--start-year 1850 --end-year 2100 --nosurfdata --ssp-rcp SSP2-4.5 --res", + "ne16", + ), + "crop-global-SSP2-4.5-C96": ( + "--start-year 1850 --end-year 2100 --nosurfdata --ssp-rcp SSP2-4.5 --res", + "C96", + ), + "crop-global-SSP2-4.5-mpasa120": ( + "--start-year 1850 --end-year 2100 --nosurfdata --ssp-rcp SSP2-4.5 --res", + "mpasa120", + ), + "crop-global-SSP3-7.0-f09": ( + "--start-year 1850 --end-year 2100 --nosurfdata --ssp-rcp SSP3-7.0 --res", + "f09", + ), + "crop-global-SSP4-3.4-f09": ( + "--start-year 1850 --end-year 2100 --nosurfdata --ssp-rcp SSP4-3.4 --res", + "f09", + ), + "crop-global-SSP4-6.0-f09": ( + "--start-year 1850 --end-year 2100 --nosurfdata --ssp-rcp SSP4-6.0 --res", + "f09", + ), + "crop-global-SSP5-3.4-f09": ( + "--start-year 1850 --end-year 2100 --nosurfdata --ssp-rcp SSP5-3.4 --res", + "f09", + ), + "crop-global-SSP5-8.5-f09": ( + "--start-year 1850 --end-year 2100 --nosurfdata --ssp-rcp SSP5-8.5 --res", + "f09", + ), + } + + # -------------------------- + # Write run script + # -------------------------- + with open(jobscript_file, "w", encoding="utf-8") as runfile: + + write_runscript( + args, + scenario, + jobscript_file, + number_of_nodes, + tasks_per_node, + account, + walltime, + args.machine, + target_list, + resolution_dict, + dataset_dict, + runfile, + ) + + print(f"echo Successfully created jobscript {jobscript_file}\n") diff --git a/python/ctsm/toolchain/gen_mksurfdata_jobscript_single.py b/python/ctsm/toolchain/gen_mksurfdata_jobscript_single.py new file mode 100755 index 0000000000..ff793165d9 --- /dev/null +++ b/python/ctsm/toolchain/gen_mksurfdata_jobscript_single.py @@ -0,0 +1,303 @@ +""" +gen_mksurfdata_jobscript_single.py generates a jobscript for running the +mksurfdata executable to generate a single fsurdat file. For detailed +instructions, see README. +""" +import os +import argparse +import logging + + +from ctsm import add_cime_to_path # pylint: disable=unused-import +from ctsm.ctsm_logging import setup_logging_pre_config, add_logging_args, process_logging_args +from ctsm.utils import abort +from ctsm.path_utils import path_to_ctsm_root +from CIME.XML.env_mach_specific import ( # pylint: disable=import-error,wrong-import-order + EnvMachSpecific, +) +from CIME.BuildTools.configure import FakeCase # pylint: disable=import-error,wrong-import-order + +logger = logging.getLogger(__name__) + + +def base_get_parser(default_js_name="mksurfdata_jobscript_single.sh"): + """ + Get parser object for the gen_mksurfdata_jobscript scripts + """ + # set up logging allowing user control + setup_logging_pre_config() + + parser = argparse.ArgumentParser( + description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter + ) + + parser.print_usage = parser.print_help + add_logging_args(parser) + + parser.add_argument( + "--account", + help="""account number (default: %(default)s)""", + action="store", + dest="account", + required=False, + default="P93300641", + ) + parser.add_argument( + "--number-of-nodes", + help="""number of derecho nodes requested (required)""", + action="store", + dest="number_of_nodes", + type=int, + required=True, + ) + parser.add_argument( + "--bld-path", + help="""Path to build directory for mksurfdata_esmf""", + action="store", + dest="bld_path", + default=os.path.join(path_to_ctsm_root(), "tools", "mksurfdata_esmf", "tool_bld"), + ) + parser.add_argument( + "--tasks-per-node", + help="""number of mpi tasks per node for derecho requested (required)""", + action="store", + dest="tasks_per_node", + type=int, + required=False, + default="128", + ) + parser.add_argument( + "--machine", + help="""currently this recognizes derecho, casper, izumi (default + %(default)s); this needs to be a cime machine, i.e. a machine + that has been ported to cime where you can build a cime model; + for details see the README in this directory""", + action="store", + dest="machine", + required=False, + choices=["derecho", "casper", "izumi"], + default="derecho", + ) + parser.add_argument( + "--jobscript-file", + help="""output jobscript file to be submitted with qsub (default: %(default)s)""", + action="store", + dest="jobscript_file", + required=False, + default=default_js_name, + ) + parser.add_argument( + "--walltime", + help="""Wallclock time for job submission default is 12:00:00)""", + action="store", + dest="walltime", + required=False, + default="12:00:00", + ) + + return parser + + +def get_parser(): + """ + Get parser object for this script. + """ + parser = base_get_parser() + parser.add_argument( + "--namelist-file", + help="""input namelist file (required)""", + action="store", + dest="namelist_file", + required=True, + ) + return parser + + +def check_parser_args(args): + """Checking for the argument parser values""" + if args.number_of_nodes < 1: + abort("Input argument --number_of_nodes is zero or negative and needs to be positive") + if args.tasks_per_node < 1: + abort("Input argument --tasks_per_node is zero or negative and needs to be positive") + if not os.path.exists(args.bld_path): + abort("Input Build path (" + args.bld_path + ") does NOT exist, aborting") + + mksurfdata_path = os.path.join(args.bld_path, "mksurfdata") + if not os.path.exists(mksurfdata_path): + abort( + "mksurfdata_esmf executable (" + + mksurfdata_path + + ") does NOT exist in the bld-path, aborting" + ) + env_mach_path = os.path.join(args.bld_path, ".env_mach_specific.sh") + if not os.path.exists(env_mach_path): + abort( + "Environment machine specific file (" + + env_mach_path + + ") does NOT exist in the bld-path, aborting" + ) + + +def write_runscript_part1( + number_of_nodes, + tasks_per_node, + machine, + account, + walltime, + runfile, + descrip="input namelist", + name="mksurfdata", +): + """ + Write run script (part 1) Batch headers + """ + runfile.write("#!/bin/bash\n") + runfile.write("# Edit the batch directives for your batch system\n") + runfile.write(f"# Below are default batch directives for {machine}\n") + runfile.write(f"#PBS -N {name}\n") + runfile.write("#PBS -j oe\n") + runfile.write("#PBS -k eod\n") + + runfile.write("#PBS -S /bin/bash\n") + if machine == "derecho": + attribs = {"mpilib": "default"} + runfile.write(f"#PBS -l walltime={walltime}\n") + runfile.write(f"#PBS -A {account}\n") + runfile.write("#PBS -q main\n") + ncpus = 128 + runfile.write( + "#PBS -l select=" + + f"{number_of_nodes}:ncpus={ncpus}:mpiprocs={tasks_per_node}:mem=218GB\n" + ) + elif machine == "casper": + attribs = {"mpilib": "default"} + ncpus = 36 + runfile.write(f"#PBS -l walltime={walltime}\n") + runfile.write(f"#PBS -A {account}\n") + runfile.write("#PBS -q casper\n") + runfile.write( + f"#PBS -l select={number_of_nodes}:ncpus={tasks_per_node}:" + f"mpiprocs={tasks_per_node}:mem=80GB\n" + ) + elif machine == "izumi": + attribs = {"mpilib": "mvapich2"} + ncpus = 48 + runfile.write(f"#PBS -l walltime={walltime}\n") + runfile.write("#PBS -q medium\n") + runfile.write(f"#PBS -l nodes={number_of_nodes}:ppn={tasks_per_node},mem=555GB -r n\n") + tool_path = os.path.dirname(os.path.abspath(__file__)) + runfile.write("\n") + runfile.write(f"cd {tool_path}\n") + + runfile.write("\n") + runfile.write( + f"# This is a batch script to run a set of resolutions for mksurfdata_esmf {descrip}\n" + ) + runfile.write( + "# NOTE: THIS SCRIPT IS AUTOMATICALLY GENERATED " + + "SO IN GENERAL YOU SHOULD NOT EDIT it!!\n\n" + ) + + # Make sure tasks_per_node doesn't exceed the number of cpus per node + if tasks_per_node > ncpus: + abort("Number of tasks per node exceeds the number of processors per node on this machine") + return attribs + + +def get_mpirun(args, attribs): + """ + Get the mpirun command for this machine + This requires a working env_mach_specific.xml file in the build directory + """ + bld_path = args.bld_path + # Get the ems_file object with standalone_configure=True + # and the fake_case object with mpilib=attribs['mpilib'] + # so as to use the get_mpirun function pointing to fake_case + ems_file = EnvMachSpecific(bld_path, standalone_configure=True) + fake_case = FakeCase(compiler=None, mpilib=attribs["mpilib"], debug=False, comp_interface=None) + total_tasks = int(args.tasks_per_node) * int(args.number_of_nodes) + cmd = ems_file.get_mpirun( + fake_case, + attribs, + job="name", + exe_only=True, + overrides={ + "total_tasks": total_tasks, + }, + ) + # cmd is a tuple: + # cmd[0] contains the mpirun command (eg mpirun, mpiexe, etc) as string + # cmd[1] contains a list of strings that we append as options to cmd[0] + # The replace function removes unnecessary characters that appear in + # some such options + executable = f'time {cmd[0]} {" ".join(cmd[1])}'.replace("ENV{", "").replace("}", "") + + mksurfdata_path = os.path.join(bld_path, "mksurfdata") + env_mach_path = os.path.join(bld_path, ".env_mach_specific.sh") + + return (executable, mksurfdata_path, env_mach_path) + + +def write_runscript_part2(namelist_file, runfile, executable, mksurfdata_path, env_mach_path): + """ + Write run script (part 2) + """ + runfile.write( + "# Run env_mach_specific.sh to control the machine " + "dependent environment including the paths to " + "compilers and libraries external to cime such as netcdf" + ) + runfile.write(f"\n. {env_mach_path}\n") + check = 'if [ $? != 0 ]; then echo "Error running env_mach_specific script"; exit -4; fi' + runfile.write(f"{check} \n") + runfile.write( + "# Edit the mpirun command to use the MPI executable " + "on your system and the arguments it requires \n" + ) + output = f"{executable} {mksurfdata_path} < {namelist_file}" + runfile.write(f"{output} \n") + logger.info("run command is %s", output) + + check = f'if [ $? != 0 ]; then echo "Error running for namelist {namelist_file}"; exit -4; fi' + runfile.write(f"{check} \n") + runfile.write("echo Successfully ran resolution\n") + + +def main(): + """ + See docstring at the top. + """ + # -------------------------- + # Obtain input args + # -------------------------- + args = get_parser().parse_args() + process_logging_args(args) + check_parser_args(args) + namelist_file = args.namelist_file + jobscript_file = args.jobscript_file + number_of_nodes = args.number_of_nodes + tasks_per_node = args.tasks_per_node + machine = args.machine + account = args.account + walltime = args.walltime + + # -------------------------- + # Write to file + # -------------------------- + with open(jobscript_file, "w", encoding="utf-8") as runfile: + # -------------------------- + # Write batch header (part 1) + # -------------------------- + attribs = write_runscript_part1( + number_of_nodes, tasks_per_node, machine, account, walltime, runfile + ) + # -------------------------- + # Obtain mpirun command from env_mach_specific.xml + # -------------------------- + (executable, mksurfdata_path, env_mach_path) = get_mpirun(args, attribs) + # -------------------------- + # Write commands to run + # -------------------------- + write_runscript_part2(namelist_file, runfile, executable, mksurfdata_path, env_mach_path) + + print(f"echo Successfully created jobscript {jobscript_file}\n") diff --git a/python/ctsm/toolchain/gen_mksurfdata_namelist.py b/python/ctsm/toolchain/gen_mksurfdata_namelist.py new file mode 100755 index 0000000000..8a953c39df --- /dev/null +++ b/python/ctsm/toolchain/gen_mksurfdata_namelist.py @@ -0,0 +1,928 @@ +""" +gen_mksurfdata_namelist.py generates a namelist for use with the mksurfdata +executable. For detailed instructions, see README. +""" +import os +import sys +import xml.etree.ElementTree as ET +import logging +import argparse +import textwrap +import subprocess +from datetime import datetime +import netCDF4 + +from ctsm.path_utils import path_to_ctsm_root +from ctsm.ctsm_logging import setup_logging_pre_config, add_logging_args, process_logging_args + +logger = logging.getLogger(__name__) + +# valid options for SSP/RCP scenarios +valid_opts = { + "ssp-rcp": [ + "SSP1-2.6", + "SSP3-7.0", + "SSP5-3.4", + "SSP2-4.5", + "SSP1-1.9", + "SSP4-3.4", + "SSP4-6.0", + "SSP5-8.5", + "none", + ] +} + + +def get_parser(): + """ + Get parser object for this script. + """ + # set up logging allowing user control + setup_logging_pre_config() + + parser = argparse.ArgumentParser( + description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter + ) + + parser.print_usage = parser.print_help + add_logging_args(parser) + + parser.add_argument( + "--start-year", + help=textwrap.dedent( + """\ + Simulation start year. + [Required]""" + ), + action="store", + dest="start_year", + required=True, + type=int, + ) + parser.add_argument( + "--end-year", + help=textwrap.dedent( + """\ + Simulation end year. + [Required]""" + ), + action="store", + dest="end_year", + required=True, + type=int, + ) + parser.add_argument( + "--res", + help=""" + Model resolution (required) + To see available supported resolutions, simply invoke this command + with a --res unknown option. For custom resolutions, provide a grid + name of your choosing to be used in the name of the fsurdat file. + """, + action="store", + dest="res", + required=True, + ) + parser.add_argument( + "--model-mesh", + help=""" + model mesh [default: %(default)s] + Ignore --res and use --model-mesh to be this file + """, + action="store", + dest="force_model_mesh_file", + required=False, + default=None, + ) + parser.add_argument( + "--namelist", + help=""" + name of output namelist filename + if NOT given the name will be the same as the surface + dataset name with a *.namelist extension rather than *.nc + """, + action="store", + dest="namelist_fname", + required=False, + default=None, + ) + parser.add_argument( + "--model-mesh-nx", + help=""" + model mesh [default: %(default)s] + Required when using --model-mesh: set nx to the grid's number of + columns; expect nx x ny = elementCount for consistency with the + model mesh + """, + action="store", + dest="force_model_mesh_nx", + required=False, + default=None, + ) + parser.add_argument( + "--model-mesh-ny", + help=""" + model mesh [default: %(default)s] + Required when using --model-mesh: set ny to the grid's number of + rows; expect nx x ny = elementCount for consistency with the model + mesh + """, + action="store", + dest="force_model_mesh_ny", + required=False, + default=None, + ) + parser.add_argument( + "--glc-nec", + help=""" + Number of glacier elevation classes to use. [default: %(default)s] + """, + action="store", + dest="glc_nec", + type=int, + default=10, + ) + parser.add_argument( + "--ssp-rcp", + help=""" + Shared Socioeconomic Pathway and Representative + Concentration Pathway Scenario name(s). + [default: %(default)s] + """, + action="store", + dest="ssp_rcp", + required=False, + choices=valid_opts["ssp-rcp"], + default="none", + ) + parser.add_argument( + "--rawdata-dir", + help=""" + /path/of/root/of/input/data + on izumi use /fs/cgd/csm/inputdata + [default: %(default)s] + """, + action="store", + dest="input_path", + default="/glade/campaign/cesm/cesmdata/inputdata/", + ) + parser.add_argument( + "--vic", + help=""" + Flag for adding the fields required for the VIC model. + [default: %(default)s] + """, + action="store_true", + dest="vic_flag", + default=False, + ) + parser.add_argument( + "--inlandwet", + help=""" + Flag for including inland wetlands. + [default: %(default)s] + """, + action="store_true", + dest="inlandwet", + default=False, + ) + parser.add_argument( + "--glc", + help=""" + Flag for adding the optional 3D glacier fields for verification of the glacier model. + [default: %(default)s] + """, + action="store_true", + dest="glc_flag", + default=False, + ) + parser.add_argument( + "--hires_pft", + help=""" + If you want to use the high-resolution pft dataset rather + than the default lower resolution dataset. + (Low resolution is at quarter-degree, high resolution at 3-minute) + [Note: hires only available for 1850 and 2005.] + [default: %(default)s] + """, + action="store_true", + dest="hres_pft", + default=False, + ) + parser.add_argument( + "--hires_soitex", + help=""" + If you want to use the high-resolution soil texture dataset rather + than the default lower resolution dataset. + (Low resolution is 5x5min, high resolution 30-second) + [default: %(default)s] + """, + action="store_true", + dest="hres_soitex", + default=False, + ) + parser.add_argument( + "--nosurfdata", + help=""" + Do not output a surface datase + This is useful if you only want a landuse_timeseries file + [default: %(default)s] + """, + action="store_true", + dest="surfdata_flag", + default=False, + ) + parser.add_argument( + "--nocrop", + help=""" + Do not create datasets with the extensive list of prognostic crop types. + [default: %(default)s] + """, + action="store_true", + dest="crop_flag", + default=False, + ) + parser.add_argument( + "--potveg_flag", + help=""" + Use Potential Vegetation for pft_years + [default: %(default)s] + """, + action="store_true", + dest="potveg_flag", + default=False, + ) + return parser + + +def main(): + """ + See docstring at the top. + """ + # pylint: disable=too-many-statements + args = get_parser().parse_args() + process_logging_args(args) + + start_year = args.start_year + end_year = args.end_year + ssp_rcp = args.ssp_rcp + res = args.res + force_model_mesh_file = args.force_model_mesh_file + force_model_mesh_nx = args.force_model_mesh_nx + force_model_mesh_ny = args.force_model_mesh_ny + input_path = args.input_path + nocrop_flag = args.crop_flag + nosurfdata_flag = args.surfdata_flag + vic_flag = args.vic_flag + inlandwet = args.inlandwet + glc_flag = args.glc_flag + potveg = args.potveg_flag + glc_nec = args.glc_nec + + hires_pft, hires_soitex = process_hires_options(args, start_year, end_year) + + if force_model_mesh_file is not None: + open_mesh_file(force_model_mesh_file, force_model_mesh_nx, force_model_mesh_ny) + + hostname = os.getenv("HOSTNAME") + logname = os.getenv("LOGNAME") + + logger.info("hostname is %s", hostname) + logger.info("logname is %s", logname) + + if ssp_rcp == "none": + check_ssp_years(start_year, end_year) + + # determine pft_years - needed to parse xml file + pft_years_ssp, pft_years = determine_pft_years(start_year, end_year, potveg) + + # Create land-use txt file for a transient case. + # Determine the run type and if a transient run create output landuse txt file + if end_year > start_year: + run_type = "transient" + else: + run_type = "timeslice" + logger.info("run_type = %s", run_type) + + # error check on glc_nec + if (glc_nec <= 0) or (glc_nec >= 100): + raise argparse.ArgumentTypeError("ERROR: glc_nec must be between 1 and 99.") + + # create attribute list for parsing xml file + attribute_list = { + "hires_pft": hires_pft, + "hires_soitex": hires_soitex, + "pft_years": pft_years, + "pft_years_ssp": pft_years_ssp, + "ssp_rcp": ssp_rcp, + "res": res, + } + + # determine input rawdata + tool_path, must_run_download_input_data, rawdata_files = determine_input_rawdata( + start_year, + input_path, + attribute_list, + ) + + # determine output mesh + determine_output_mesh(res, force_model_mesh_file, input_path, rawdata_files, tool_path) + + # Determine num_pft + if nocrop_flag: + num_pft = "16" + else: + num_pft = "78" + logger.info("num_pft is %s", num_pft) + + # Write out if surface dataset will be created + if nosurfdata_flag: + logger.info("surface dataset will not be created") + else: + logger.info("surface dataset will be created") + + ( + landuse_fname, + fdyndat, + nlfname, + fsurdat, + fsurlog, + must_run_download_input_data, + ) = get_file_paths( + args, + start_year, + end_year, + ssp_rcp, + res, + pft_years, + run_type, + rawdata_files, + num_pft, + must_run_download_input_data, + ) + + git_desc_cmd = f"git -C {tool_path} describe" + try: + # The "git -C" option permits a system test to run this tool from + # elsewhere while running the git command from the tool_path + gitdescribe = subprocess.check_output(git_desc_cmd, shell=True).strip() + except subprocess.CalledProcessError as error: + # In case the "git -C" option is unavailable, as on casper (2022/5/24) + # Still, this does NOT allow the system test to work on machines + # without git -C + logger.info("git -C option unavailable on casper as of 2022/7/2 %s", error) + gitdescribe = subprocess.check_output("git describe", shell=True).strip() + gitdescribe = gitdescribe.decode("utf-8") + + # The below two overrides are only used for testing and validation + # it takes a long time to generate the mapping files + # from 1km to the following two resolutions since the output mesh has so few points + if res == "10x15": + mksrf_ftopostats_override = os.path.join( + input_path, "lnd", "clm2", "rawdata", "surfdata_topo_10x15_c220303.nc" + ) + logger.info("will override mksrf_ftopostats with = %s", mksrf_ftopostats_override) + else: + mksrf_ftopostats_override = "" + + # ---------------------------------------- + # Write output namelist file + # ---------------------------------------- + + with open(nlfname, "w", encoding="utf-8") as nlfile: + nlfile.write("&mksurfdata_input \n") + + # ------------------- + # raw input data + # ------------------- + must_run_download_input_data = write_nml_rawinput( + start_year, + force_model_mesh_file, + force_model_mesh_nx, + force_model_mesh_ny, + vic_flag, + rawdata_files, + landuse_fname, + mksrf_ftopostats_override, + nlfile, + must_run_download_input_data, + ) + + # ------------------- + # output data + # ------------------- + write_nml_outdata( + nosurfdata_flag, + vic_flag, + inlandwet, + glc_flag, + hostname, + logname, + num_pft, + fdyndat, + fsurdat, + fsurlog, + gitdescribe, + nlfile, + ) + + nlfile.write("/ \n") + + if must_run_download_input_data: + temp_nlfname = "surfdata.namelist" + os.rename(nlfname, temp_nlfname) + nlfname = temp_nlfname + + print(f"Successfully created input namelist file {nlfname}") + + +def process_hires_options(args, start_year, end_year): + """ + Process options related to hi-res + """ + if args.hres_pft: + if (start_year == 1850 and end_year == 1850) or (start_year == 2005 and end_year == 2005): + hires_pft = "on" + else: + error_msg = ( + "ERROR: for --hires_pft you must set both start-year " + "and end-year to 1850 or to 2005" + ) + sys.exit(error_msg) + else: + hires_pft = "off" + + if args.hres_soitex: + hires_soitex = "on" + else: + hires_soitex = "off" + return hires_pft, hires_soitex + + +def check_ssp_years(start_year, end_year): + """ + Check years associated with SSP period + """ + if int(start_year) > 2015: + error_msg = ( + "ERROR: if start-year > 2015 must add an --ssp_rcp " + "argument that is not none: valid opts for ssp-rcp " + f"are {valid_opts}" + ) + sys.exit(error_msg) + elif int(end_year) > 2015: + error_msg = ( + "ERROR: if end-year > 2015 must add an --ssp-rcp " + "argument that is not none: valid opts for ssp-rcp " + f"are {valid_opts}" + ) + sys.exit(error_msg) + + +def get_file_paths( + args, + start_year, + end_year, + ssp_rcp, + res, + pft_years, + run_type, + rawdata_files, + num_pft, + must_run_download_input_data, +): + """ + Get various file paths + """ + if run_type == "transient": + landuse_fname, must_run_download_input_data = handle_transient_run( + start_year, end_year, ssp_rcp, rawdata_files, num_pft, must_run_download_input_data + ) + print(f"Successfully created input landuse file {landuse_fname}") + else: + landuse_fname = "" + + time_stamp = datetime.today().strftime("%y%m%d") + if ssp_rcp == "none": + if pft_years == "PtVg": + ssp_rcp_name = "PtVeg_nourb" + else: + ssp_rcp_name = "hist" + else: + ssp_rcp_name = ssp_rcp + if int(end_year) == int(start_year): + fdyndat = "" + else: + fdyndat = ( + f"landuse.timeseries_{res}_{ssp_rcp_name}" + f"_{start_year}-{end_year}_{num_pft}pfts_c{time_stamp}.nc" + ) + + prefix = f"surfdata_{res}_{ssp_rcp_name}_{start_year}_{num_pft}pfts_c{time_stamp}." + + if args.namelist_fname is None: + nlfname = f"{prefix}namelist" + else: + nlfname = args.namelist_fname + + fsurdat = f"{prefix}nc" + fsurlog = f"{prefix}log" + return landuse_fname, fdyndat, nlfname, fsurdat, fsurlog, must_run_download_input_data + + +def determine_pft_years(start_year, end_year, potveg): + """ + determine pft_years - needed to parse xml file + """ + pft_years_ssp = "-999" + if potveg: + pft_years = "PtVg" + elif int(start_year) == 1850 and int(end_year) == 1850: + pft_years = "1850" + elif int(start_year) == 2000 and int(end_year) == 2000: + pft_years = "2000" + elif int(start_year) == 2005 and int(end_year) == 2005: + pft_years = "2005" + elif int(start_year) >= 850 and int(end_year) <= 1849: + pft_years = "0850-1849" + elif int(start_year) >= 1850 and int(start_year) <= 2100 and int(end_year) <= 2015: + pft_years = "1850-2015" + elif int(start_year) >= 1850 and int(start_year) <= 2100 and int(end_year) <= 2100: + pft_years = "1850-2015" + pft_years_ssp = "2016-2100" + elif int(start_year) >= 2016 and int(start_year) <= 2100 and int(end_year) <= 2100: + pft_years = "-999" + pft_years_ssp = "2016-2100" + else: + error_msg = ( + f"ERROR: start_year is {start_year} and end_year is " + f"{end_year}; expected start/end-year options are: " + "- 1850, 2000, 2005 for time-slice options " + "- in the range from 850 to 1849 " + "- in the range from 1850 to 2100 " + "- TODO in the range from 2101 to 2300 " + "- OR user must set the potveg_flag " + ) + sys.exit(error_msg) + + logger.info("pft_years = %s", pft_years) + return pft_years_ssp, pft_years + + +def write_nml_outdata( + nosurfdata_flag, + vic_flag, + inlandwet, + glc_flag, + hostname, + logname, + num_pft, + fdyndat, + fsurdat, + fsurlog, + gitdescribe, + nlfile, +): + """ + Write output namelist file: output data + """ + # ------------------- + # output data files + # ------------------- + if nosurfdata_flag: + nlfile.write(" fsurdat = ' ' \n") + else: + nlfile.write(f" fsurdat = '{fsurdat}'\n") + nlfile.write(f" fsurlog = '{fsurlog}' \n") + nlfile.write(f" fdyndat = '{fdyndat}' \n") + + # ------------------- + # output data logicals + # ------------------- + nlfile.write(f" numpft = {num_pft} \n") + nlfile.write(f" no_inlandwet = .{str(not inlandwet).lower()}. \n") + nlfile.write(f" outnc_3dglc = .{str(glc_flag).lower()}. \n") + nlfile.write(f" outnc_vic = .{str(vic_flag).lower()}. \n") + nlfile.write(" outnc_large_files = .false. \n") + nlfile.write(" outnc_double = .true. \n") + nlfile.write(f" logname = '{logname}' \n") + nlfile.write(f" hostname = '{hostname}' \n") + nlfile.write(f" gitdescribe = '{gitdescribe}' \n") + + +def write_nml_rawinput( + start_year, + force_model_mesh_file, + force_model_mesh_nx, + force_model_mesh_ny, + vic_flag, + rawdata_files, + landuse_fname, + mksrf_ftopostats_override, + nlfile, + must_run_download_input_data, +): + """ + Write output namelist file: raw input data + """ + # pylint: disable=too-many-statements + if force_model_mesh_file is None: + mksrf_fgrid_mesh_nx = rawdata_files["mksrf_fgrid_mesh_nx"] + mksrf_fgrid_mesh_ny = rawdata_files["mksrf_fgrid_mesh_ny"] + mksrf_fgrid_mesh = rawdata_files["mksrf_fgrid_mesh"] + else: + mksrf_fgrid_mesh_nx = force_model_mesh_nx + mksrf_fgrid_mesh_ny = force_model_mesh_ny + mksrf_fgrid_mesh = force_model_mesh_file + nlfile.write(f" mksrf_fgrid_mesh = '{mksrf_fgrid_mesh}' \n") + nlfile.write(f" mksrf_fgrid_mesh_nx = {mksrf_fgrid_mesh_nx} \n") + nlfile.write(f" mksrf_fgrid_mesh_ny = {mksrf_fgrid_mesh_ny} \n") + + for key, value in rawdata_files.items(): + if key == "mksrf_ftopostats" and mksrf_ftopostats_override != "": + nlfile.write(f" mksrf_ftopostats_override = '{mksrf_ftopostats_override}' \n") + elif "_fvic" not in key and "mksrf_fvegtyp" not in key and "mksrf_fgrid" not in key: + # write everything else + nlfile.write(f" {key} = '{value}' \n") + + if start_year <= 2015: + mksrf_fvegtyp = rawdata_files["mksrf_fvegtyp"] + mksrf_fvegtyp_mesh = rawdata_files["mksrf_fvegtyp_mesh"] + mksrf_fhrvtyp = rawdata_files["mksrf_fvegtyp"] + mksrf_fhrvtyp_mesh = rawdata_files["mksrf_fvegtyp_mesh"] + mksrf_fpctlak = rawdata_files["mksrf_fvegtyp_lake"] + mksrf_furban = rawdata_files["mksrf_fvegtyp_urban"] + else: + mksrf_fvegtyp = rawdata_files["mksrf_fvegtyp_ssp"] + mksrf_fvegtyp_mesh = rawdata_files["mksrf_fvegtyp_ssp_mesh"] + mksrf_fhrvtyp = rawdata_files["mksrf_fvegtyp_ssp"] + mksrf_fhrvtyp_mesh = rawdata_files["mksrf_fvegtyp_ssp_mesh"] + mksrf_fpctlak = rawdata_files["mksrf_fvegtyp_ssp_lake"] + mksrf_furban = rawdata_files["mksrf_fvegtyp_ssp_urban"] + if "%y" in mksrf_fvegtyp: + mksrf_fvegtyp = mksrf_fvegtyp.replace("%y", str(start_year)) + if "%y" in mksrf_fhrvtyp: + mksrf_fhrvtyp = mksrf_fhrvtyp.replace("%y", str(start_year)) + if "%y" in mksrf_fpctlak: + mksrf_fpctlak = mksrf_fpctlak.replace("%y", str(start_year)) + if "%y" in mksrf_furban: + mksrf_furban = mksrf_furban.replace("%y", str(start_year)) + if not os.path.isfile(mksrf_fvegtyp): + print("WARNING: input mksrf_fvegtyp file " f"{mksrf_fvegtyp} does not exist") + print("WARNING: run ./download_input_data to try TO " "OBTAIN MISSING FILES") + must_run_download_input_data = True + if not os.path.isfile(mksrf_fhrvtyp): + print("WARNING: input mksrf_fhrvtyp file " f"{mksrf_fhrvtyp} does not exist") + print("WARNING: run ./download_input_data to try TO " "OBTAIN MISSING FILES") + must_run_download_input_data = True + if not os.path.isfile(mksrf_fpctlak): + print("WARNING: input mksrf_fpctlak file " f"{mksrf_fpctlak} does not exist") + print("WARNING: run ./download_input_data to try TO " "OBTAIN MISSING FILES") + must_run_download_input_data = True + if not os.path.isfile(mksrf_furban): + print("WARNING: input mksrf_furban file " f"{mksrf_furban} does not exist") + print("WARNING: run ./download_input_data to try TO " "OBTAIN MISSING FILES") + must_run_download_input_data = True + nlfile.write(f" mksrf_fvegtyp = '{mksrf_fvegtyp}' \n") + nlfile.write(f" mksrf_fvegtyp_mesh = '{mksrf_fvegtyp_mesh}' \n") + nlfile.write(f" mksrf_fhrvtyp = '{mksrf_fhrvtyp}' \n") + nlfile.write(f" mksrf_fhrvtyp_mesh = '{mksrf_fhrvtyp_mesh}' \n") + nlfile.write(f" mksrf_fpctlak = '{mksrf_fpctlak}' \n") + nlfile.write(f" mksrf_furban = '{mksrf_furban}' \n") + + if vic_flag: + mksrf_fvic = rawdata_files["mksrf_fvic"] + nlfile.write(f" mksrf_fvic = '{mksrf_fvic}' \n") + mksrf_fvic_mesh = rawdata_files["mksrf_fvic_mesh"] + nlfile.write(f" mksrf_fvic_mesh = '{mksrf_fvic_mesh}' \n") + + nlfile.write(f" mksrf_fdynuse = '{landuse_fname} ' \n") + return must_run_download_input_data + + +def handle_transient_run( + start_year, end_year, ssp_rcp, rawdata_files, num_pft, must_run_download_input_data +): + """ + Settings and printout for when run_type is "transient" + """ + if ssp_rcp == "none": + landuse_fname = f"landuse_timeseries_hist_{start_year}-{end_year}_{num_pft}pfts.txt" + else: + landuse_fname = f"landuse_timeseries_{ssp_rcp}_{start_year}-{end_year}_{num_pft}pfts.txt" + + with open(landuse_fname, "w", encoding="utf-8") as landuse_file: + for year in range(start_year, end_year + 1): + year_str = str(year) + if year <= 2015: + file1 = rawdata_files["mksrf_fvegtyp"] + file2 = rawdata_files["mksrf_fvegtyp_urban"] + file3 = rawdata_files["mksrf_fvegtyp_lake"] + else: + file1 = rawdata_files["mksrf_fvegtyp_ssp"] + file2 = rawdata_files["mksrf_fvegtyp_ssp_urban"] + file3 = rawdata_files["mksrf_fvegtyp_ssp_lake"] + + landuse_input_fname = file1.replace("%y", year_str) + landuse_input_fnam2 = file2.replace("%y", year_str) + landuse_input_fnam3 = file3.replace("%y", year_str) + if not os.path.isfile(landuse_input_fname): + print("WARNING: landunit_input_fname: " f"{landuse_input_fname} does not exist") + print("WARNING: run ./download_input_data to try TO " "OBTAIN MISSING FILES") + must_run_download_input_data = True + if not os.path.isfile(landuse_input_fnam2): + print("WARNING: landunit_input_fnam2: " f"{landuse_input_fnam2} does not exist") + print("WARNING: run ./download_input_data to try TO " "OBTAIN MISSING FILES") + must_run_download_input_data = True + if not os.path.isfile(landuse_input_fnam3): + print("WARNING: landunit_input_fnam3: " f"{landuse_input_fnam3} does not exist") + print("WARNING: run ./download_input_data to try TO " "OBTAIN MISSING FILES") + must_run_download_input_data = True + + # -- Each line is written twice in the original perl code: + landuse_line = f"{landuse_input_fname:<196}{year_str}\n" + landuse_lin2 = f"{landuse_input_fnam2:<196}{year_str}\n" + landuse_lin3 = f"{landuse_input_fnam3:<196}{year_str}\n" + landuse_file.write(landuse_line) + landuse_file.write(landuse_line) + landuse_file.write(landuse_lin2) + landuse_file.write(landuse_lin3) + logger.debug("year : %s", year_str) + logger.debug(landuse_line) + return landuse_fname, must_run_download_input_data + + +def determine_output_mesh(res, force_model_mesh_file, input_path, rawdata_files, tool_path): + """ + determine output mesh + """ + xml_path = os.path.join(tool_path, "../../ccs_config/component_grids_nuopc.xml") + tree2 = ET.parse(xml_path) + root = tree2.getroot() + model_mesh = "" + for child1 in root: # this is domain tag + for _, value in child1.attrib.items(): + if value == res: + for child2 in child1: + if child2.tag == "mesh": + model_mesh = child2.text + rawdata_files["mksrf_fgrid_mesh"] = os.path.join( + input_path, model_mesh.strip("$DIN_LOC_ROOT/") + ) + if child2.tag == "nx": + rawdata_files["mksrf_fgrid_mesh_nx"] = child2.text + if child2.tag == "ny": + rawdata_files["mksrf_fgrid_mesh_ny"] = child2.text + + if not model_mesh and force_model_mesh_file is None: + valid_grids = [] + for child1 in root: # this is domain tag + for _, value in child1.attrib.items(): + valid_grids.append(value) + if res in valid_grids: + error_msg = ( + "ERROR: You have requested a valid grid for which " + "../../ccs_config/component_grids_nuopc.xml does not include a mesh " + "file. For a regular regional or 1x1 grid, you may generate the " + "fsurdat file using the subset_data tool instead. Alternatively " + "and definitely for curvilinear grids, you may generate " + "a mesh file using the workflow currently (2022/7) described in " + "https://github.com/ESCOMP/CTSM/issues/1773#issuecomment-1163432584" + "TODO Reminder to ultimately place these workflow instructions in " + "the User's Guide." + ) + sys.exit(error_msg) + else: + error_msg = f"ERROR: invalid input res {res}; " f"valid grid values are {valid_grids}" + sys.exit(error_msg) + + +def determine_input_rawdata(start_year, input_path, attribute_list): + """ + determine input rawdata + """ + # pylint: disable=too-many-statements + + # create dictionary for raw data files names + rawdata_files = {} + + must_run_download_input_data = False + tool_path = os.path.join(path_to_ctsm_root(), "tools", "mksurfdata_esmf") + xml_path = os.path.join(tool_path, "gen_mksurfdata_namelist.xml") + tree1 = ET.parse(xml_path) + root = tree1.getroot() + logger.info("root.tag: %s", root.tag) + logger.info("root.attrib: %s", root.attrib) + for child1 in root: + max_match_num = -1 + max_match_child = None + for child2 in child1: + if child2.tag == "entry": + num_match = 0 + for attrib in attribute_list: + # Get the value of the attrib for the entry + childval = child2.get(attrib, default=None) + if childval == attribute_list[attrib]: + num_match += 1 + elif childval is not None: + num_match = -1 + break + if num_match > max_match_num: + max_match_num = num_match + max_match_child = child2 + + if max_match_child is None: + # TODO slevis: Are these if-statements backwards? + # For years greater than 2015 - mksrf_fvegtyp_ssp must have a match + if start_year <= 2015: + if "mksrf_fvegtyp_ssp" not in child1.tag: + error_msg = f"ERROR: {child1.tag} has no matches" + sys.exit(error_msg) + else: + continue + else: + # For years less than 2015 - mksrf_fvegtyp must have a match + if "mksrf_fvegtyp" not in child1.tag: + error_msg = f"ERROR: {child1.tag} has no matches" + sys.exit(error_msg) + else: + continue + + for item in max_match_child: + if item.tag == "data_filename": + rawdata_files[child1.tag] = os.path.join(input_path, item.text) + if "%y" not in rawdata_files[child1.tag]: + if not os.path.isfile(rawdata_files[child1.tag]): + print( + "WARNING: input data file " + f"{rawdata_files[child1.tag]} for {child1.tag} " + "does not exist" + ) + print( + "WARNING: run ./download_input_data to try TO " "OBTAIN MISSING FILES" + ) + must_run_download_input_data = True + + if item.tag == "mesh_filename": + new_key = f"{child1.tag}_mesh" + rawdata_files[new_key] = os.path.join(input_path, item.text) + if not os.path.isfile(rawdata_files[new_key]): + print("WARNING: input mesh file " f"{rawdata_files[new_key]} does not exist") + print("WARNING: run ./download_input_data to try TO " "OBTAIN MISSING FILES") + must_run_download_input_data = True + + if item.tag == "lake_filename": + new_key = f"{child1.tag}_lake" + rawdata_files[new_key] = os.path.join(input_path, item.text) + + if item.tag == "urban_filename": + new_key = f"{child1.tag}_urban" + rawdata_files[new_key] = os.path.join(input_path, item.text) + + if item.tag == "lookup_filename": + new_key = f"{child1.tag}_lookup" + rawdata_files[new_key] = os.path.join(input_path, item.text) + return tool_path, must_run_download_input_data, rawdata_files + + +def open_mesh_file(force_model_mesh_file, force_model_mesh_nx, force_model_mesh_ny): + """ + open mesh_file to read element_count and, if available, orig_grid_dims + """ + # pylint: disable=no-name-in-module,no-member + # The above "pylint: disable" is because pylint complains that netCDF4 + # has no member Dataset, even though it does. + mesh_file = netCDF4.Dataset(force_model_mesh_file, "r") + element_count = mesh_file.dimensions["elementCount"].size + if "origGridDims" in mesh_file.variables: + orig_grid_dims = mesh_file.variables["origGridDims"] + if ( + int(force_model_mesh_nx) == orig_grid_dims[0] + and int(force_model_mesh_ny) == orig_grid_dims[1] + ): + mesh_file.close() + else: + error_msg = ( + "ERROR: Found variable origGridDims in " + f"{force_model_mesh_file} with values " + f"{orig_grid_dims[:]} that do not agree with the " + "user-entered mesh_nx and mesh_ny values of " + f"{[force_model_mesh_nx, force_model_mesh_ny]}." + ) + sys.exit(error_msg) + elif force_model_mesh_nx is None or force_model_mesh_ny is None: + error_msg = ( + "ERROR: You set --model-mesh so you MUST ALSO " + "SET --model-mesh-nx AND --model-mesh-ny" + ) + sys.exit(error_msg) + + # using force_model_mesh_nx and force_model_mesh_ny either from the + # mesh file (see previous if statement) or the user-entered values + if element_count != int(force_model_mesh_nx) * int(force_model_mesh_ny): + error_msg = ( + "ERROR: The product of " + "--model-mesh-nx x --model-mesh-ny must equal " + "exactly elementCount in --model-mesh" + ) + sys.exit(error_msg) diff --git a/src/biogeochem/CNDVEstablishmentMod.F90 b/src/biogeochem/CNDVEstablishmentMod.F90 index 461b01b869..9606b7bbe2 100644 --- a/src/biogeochem/CNDVEstablishmentMod.F90 +++ b/src/biogeochem/CNDVEstablishmentMod.F90 @@ -55,6 +55,7 @@ subroutine Establishment(bounds, & ! ! !LOCAL VARIABLES: integer :: g,l,c,p,m ! indices + ! TODO slevis: Is begg - endg backwards in the next line? integer :: fn, filterg(bounds%begg-bounds%endg+1) ! local gridcell filter for error check ! ! gridcell level variables diff --git a/src/biogeochem/CropType.F90 b/src/biogeochem/CropType.F90 index 713e9fe5d9..760aa21b76 100644 --- a/src/biogeochem/CropType.F90 +++ b/src/biogeochem/CropType.F90 @@ -775,7 +775,7 @@ subroutine CropUpdateAccVars(this, bounds, t_ref2m_patch, t_soisno_col) use accumulMod , only : update_accum_field, extract_accum_field, accumResetVal use shr_const_mod , only : SHR_CONST_CDAY, SHR_CONST_TKFRZ use clm_time_manager , only : get_step_size, get_nstep - use clm_varpar , only : nlevsno, nlevgrnd + use clm_varpar , only : nlevsno, nlevmaxurbgrnd use pftconMod , only : nswheat, nirrig_swheat, pftcon use pftconMod , only : nwwheat, nirrig_wwheat use pftconMod , only : nsugarcane, nirrig_sugarcane @@ -806,7 +806,7 @@ subroutine CropUpdateAccVars(this, bounds, t_ref2m_patch, t_soisno_col) ! Enforce expected array sizes SHR_ASSERT_ALL_FL((ubound(t_ref2m_patch) == (/endp/)) , sourcefile, __LINE__) - SHR_ASSERT_ALL_FL((ubound(t_soisno_col) == (/endc,nlevgrnd/)) , sourcefile, __LINE__) + SHR_ASSERT_ALL_FL((ubound(t_soisno_col) == (/endc,nlevmaxurbgrnd/)) , sourcefile, __LINE__) dtime = get_step_size() nstep = get_nstep() diff --git a/src/biogeochem/ch4Mod.F90 b/src/biogeochem/ch4Mod.F90 index f199e7913f..95c3762d8d 100644 --- a/src/biogeochem/ch4Mod.F90 +++ b/src/biogeochem/ch4Mod.F90 @@ -1684,7 +1684,7 @@ subroutine ch4 (bounds, num_soilc, filter_soilc, num_lakec, filter_lakec, & use ch4varcon , only : replenishlakec, allowlakeprod, ch4offline use clm_varcon , only : secspday use ch4varcon , only : finundation_mtd, finundation_mtd_h2osfc - use clm_time_manager, only : is_beg_curr_year + use clm_time_manager, only : is_beg_curr_year, is_first_step use dynSubgridControlMod, only : get_do_transient_lakes ! ! !ARGUMENTS: @@ -2324,10 +2324,13 @@ subroutine ch4 (bounds, num_soilc, filter_soilc, num_lakec, filter_lakec, & ! Gricell level balance ! - ! Skip the check if it's the beginning of a new year and dynamic lakes are on - ! See (https://github.com/ESCOMP/CTSM/issues/1356#issuecomment-905963583) + ! Skip the check if dynamic lakes are on and it's + ! - the beginning of a new year (ok for restart runs) OR + ! - the beginning of a simulation (needed for hybrid/startup runs) + ! See (https://github.com/ESCOMP/CTSM/issues/43#issuecomment-1282609233) ! - if ( is_beg_curr_year() .and. get_do_transient_lakes() )then + if ( is_beg_curr_year() .and. get_do_transient_lakes() .or. & + is_first_step() .and. get_do_transient_lakes() )then ch4_first_time_grc(begg:endg) = .true. end if diff --git a/src/biogeophys/EnergyFluxType.F90 b/src/biogeophys/EnergyFluxType.F90 index 685663b83d..2e709596a1 100644 --- a/src/biogeophys/EnergyFluxType.F90 +++ b/src/biogeophys/EnergyFluxType.F90 @@ -170,7 +170,7 @@ subroutine InitAllocate(this, bounds) ! ! !USES: use shr_infnan_mod , only : nan => shr_infnan_nan, assignment(=) - use clm_varpar , only : nlevsno, nlevgrnd, nlevlak + use clm_varpar , only : nlevgrnd implicit none ! ! !ARGUMENTS: @@ -287,7 +287,7 @@ subroutine InitHistory(this, bounds, is_simple_buildtemp, is_prog_buildtemp) ! ! !USES: use shr_infnan_mod , only : nan => shr_infnan_nan, assignment(=) - use clm_varpar , only : nlevsno, nlevgrnd + use clm_varpar , only : nlevgrnd use clm_varctl , only : use_cn, use_hydrstress use histFileMod , only : hist_addfld1d, hist_addfld2d, no_snow_normal use ncdio_pio , only : ncd_inqvdlen @@ -700,13 +700,8 @@ subroutine InitCold(this, bounds, t_grnd_col, is_simple_buildtemp, is_prog_build ! ! !USES: use shr_kind_mod , only : r8 => shr_kind_r8 - use shr_const_mod , only : SHR_CONST_TKFRZ - use clm_varpar , only : nlevsoi, nlevgrnd, nlevsno, nlevlak, nlevurb - use clm_varcon , only : denice, denh2o, sb - use landunit_varcon , only : istwet, istsoil, istdlak - use column_varcon , only : icol_road_imperv, icol_roof, icol_sunwall - use column_varcon , only : icol_shadewall, icol_road_perv - use clm_varctl , only : use_vancouver, use_mexicocity + use clm_varpar , only : nlevgrnd + use clm_varcon , only : sb implicit none ! ! !ARGUMENTS: @@ -936,7 +931,6 @@ subroutine InitAccBuffer (this, bounds) ! !USES use accumulMod , only : init_accum_field use clm_time_manager , only : get_step_size_real - use shr_const_mod , only : SHR_CONST_CDAY, SHR_CONST_TKFRZ ! ! !ARGUMENTS: class(energyflux_type) :: this @@ -964,7 +958,6 @@ subroutine InitAccVars(this, bounds) ! is read in and the accumulation buffer is obtained) ! ! !USES - use accumulMod , only : init_accum_field, extract_accum_field use clm_time_manager , only : get_nstep use clm_varctl , only : nsrest, nsrStartup use abortutils , only : endrun @@ -994,7 +987,6 @@ end subroutine InitAccVars subroutine UpdateAccVars (this, bounds) ! ! USES - use shr_const_mod , only : SHR_CONST_CDAY, SHR_CONST_TKFRZ use clm_time_manager , only : get_step_size, get_nstep, is_end_curr_day, get_curr_date use accumulMod , only : update_accum_field, extract_accum_field, accumResetVal use abortutils , only : endrun diff --git a/src/biogeophys/test/Photosynthesis_test/test_Photosynthesis.pf b/src/biogeophys/test/Photosynthesis_test/test_Photosynthesis.pf index faa506a99f..9c2d6364f7 100644 --- a/src/biogeophys/test/Photosynthesis_test/test_Photosynthesis.pf +++ b/src/biogeophys/test/Photosynthesis_test/test_Photosynthesis.pf @@ -38,7 +38,7 @@ contains soil_layerstruct_predefined = '20SL_8.5m' call setup_ncells_single_veg_patch(ncells=1, pft_type=1) - call clm_varpar_init( actual_maxsoil_patches=17, surf_numpft=15, surf_numcft=2 ) + call clm_varpar_init( actual_maxsoil_patches=17, surf_numpft=15, surf_numcft=2, actual_nlevurb=5 ) call this%photo%Init( bounds ) call this%photo%setParamsForTesting( ) diff --git a/src/main/clm_initializeMod.F90 b/src/main/clm_initializeMod.F90 index ab59ea5447..9bf0cc59a2 100644 --- a/src/main/clm_initializeMod.F90 +++ b/src/main/clm_initializeMod.F90 @@ -17,7 +17,7 @@ module clm_initializeMod use clm_varctl , only : use_lch4, use_cn, use_cndv, use_c13, use_c14, nhillslope use clm_varctl , only : use_soil_moisture_streams use clm_instur , only : wt_lunit, urban_valid, wt_nat_patch, wt_cft, fert_cft - use clm_instur , only : irrig_method, wt_glc_mec, topo_glc_mec, haslake, ncolumns_hillslope, pct_urban_max + use clm_instur , only : irrig_method, wt_glc_mec, topo_glc_mec, pct_lake_max, pct_urban_max, ncolumns_hillslope use perf_mod , only : t_startf, t_stopf use readParamsMod , only : readParameters use ncdio_pio , only : file_desc_t @@ -41,6 +41,7 @@ module clm_initializeMod public :: initialize2 ! Phase two initialization integer :: actual_numcft ! numcft from sfc dataset + integer :: actual_nlevurb ! nlevurb from sfc dataset integer :: actual_numpft ! numpft from sfc dataset !----------------------------------------------------------------------- @@ -57,7 +58,7 @@ subroutine initialize1(dtime) use clm_varcon , only: clm_varcon_init use landunit_varcon , only: landunit_varcon_init use clm_varctl , only: fsurdat, version - use surfrdMod , only: surfrd_get_num_patches + use surfrdMod , only: surfrd_get_num_patches, surfrd_get_nlevurb use controlMod , only: control_init, control_print, NLFilename use ncdio_pio , only: ncd_pio_init use initGridCellsMod , only: initGridCells @@ -100,6 +101,7 @@ subroutine initialize1(dtime) call control_init(dtime) call ncd_pio_init() call surfrd_get_num_patches(fsurdat, actual_maxsoil_patches, actual_numpft, actual_numcft) + call surfrd_get_nlevurb(fsurdat, actual_nlevurb) ! If fates is on, we override actual_maxsoil_patches. FATES dictates the ! number of patches per column. We still use numcft from the surface @@ -108,7 +110,7 @@ subroutine initialize1(dtime) call CLMFatesGlobals1(actual_numpft, actual_numcft, actual_maxsoil_patches) end if - call clm_varpar_init(actual_maxsoil_patches, actual_numpft, actual_numcft) + call clm_varpar_init(actual_maxsoil_patches, actual_numpft, actual_numcft, actual_nlevurb) call decomp_cascade_par_init( NLFilename ) call clm_varcon_init( IsSimpleBuildTemp() ) call landunit_varcon_init() @@ -239,11 +241,11 @@ subroutine initialize2(ni,nj) allocate (irrig_method (begg:endg, cft_lb:cft_ub )) allocate (wt_glc_mec (begg:endg, maxpatch_glc )) allocate (topo_glc_mec (begg:endg, maxpatch_glc )) - allocate (haslake (begg:endg )) + allocate (pct_lake_max (begg:endg )) + allocate (pct_urban_max(begg:endg, numurbl )) if (use_hillslope) then allocate (ncolumns_hillslope (begg:endg )) endif - allocate (pct_urban_max(begg:endg, numurbl )) allocate (wt_nat_patch (begg:endg, surfpft_lb:surfpft_ub )) ! Read list of Patches and their corresponding parameter values @@ -329,7 +331,7 @@ subroutine initialize2(ni,nj) ! Some things are kept until the end of initialize2; urban_valid is kept through the ! end of the run for error checking, pct_urban_max is kept through the end of the run ! for reweighting in subgridWeights. - deallocate (wt_lunit, wt_cft, wt_glc_mec, haslake) + deallocate (wt_lunit, wt_cft, wt_glc_mec, pct_lake_max) if (use_hillslope) deallocate (ncolumns_hillslope) ! Determine processor bounds and clumps for this processor diff --git a/src/main/clm_varctl.F90 b/src/main/clm_varctl.F90 index 389ed50f88..7d0b2b55ad 100644 --- a/src/main/clm_varctl.F90 +++ b/src/main/clm_varctl.F90 @@ -177,6 +177,11 @@ module clm_varctl ! true => make ALL patches, cols & landunits active (even if weight is 0) logical, public :: all_active = .false. + ! true => any ocean (i.e., "wetland") points on the surface dataset are converted to + ! bare ground (or whatever vegetation is given in that grid cell... but typically this + ! will be bare ground) + logical, public :: convert_ocean_to_land = .false. + logical, public :: collapse_urban = .false. ! true => collapse urban landunits to the dominant urban landunit; default = .false. means "do nothing" i.e. keep all urban landunits as found in the input data integer, public :: n_dom_landunits = -1 ! # of dominant landunits; determines the number of active landunits; default = 0 (set in namelist_defaults_ctsm.xml) means "do nothing" integer, public :: n_dom_pfts = -1 ! # of dominant pfts; determines the number of active pfts; default = 0 (set in namelist_defaults_ctsm.xml) means "do nothing" diff --git a/src/main/clm_varpar.F90 b/src/main/clm_varpar.F90 index ffa851482a..4ddacc38e4 100644 --- a/src/main/clm_varpar.F90 +++ b/src/main/clm_varpar.F90 @@ -122,7 +122,7 @@ module clm_varpar contains !------------------------------------------------------------------------------ - subroutine clm_varpar_init(actual_maxsoil_patches, surf_numpft, surf_numcft) + subroutine clm_varpar_init(actual_maxsoil_patches, surf_numpft, surf_numcft, actual_nlevurb) ! ! !DESCRIPTION: ! Initialize module variables @@ -135,6 +135,7 @@ subroutine clm_varpar_init(actual_maxsoil_patches, surf_numpft, surf_numcft) ! from fates (via its parameter file) integer, intent(in) :: surf_numpft ! Number of PFTs in the surf dataset integer, intent(in) :: surf_numcft ! Number of CFTs in the surf dataset + integer, intent(in) :: actual_nlevurb ! nlevurb from surface dataset ! ! !LOCAL VARIABLES: ! @@ -195,7 +196,7 @@ subroutine clm_varpar_init(actual_maxsoil_patches, surf_numpft, surf_numcft) mxharvests = mxsowings + 1 nlevsoifl = 10 - nlevurb = 5 + nlevurb = actual_nlevurb if ( masterproc ) write(iulog, *) 'soil_layerstruct_predefined varpar ', soil_layerstruct_predefined if ( masterproc ) write(iulog, *) 'soil_layerstruct_userdefined varpar ', soil_layerstruct_userdefined diff --git a/src/main/clm_varsur.F90 b/src/main/clm_varsur.F90 index c49c8bb052..8ca2313801 100644 --- a/src/main/clm_varsur.F90 +++ b/src/main/clm_varsur.F90 @@ -47,15 +47,15 @@ module clm_instur real(r8), pointer :: topo_glc_mec(:,:) ! whether we have lake to initialise in each grid cell - logical , pointer :: haslake(:) + real(r8), pointer :: pct_lake_max(:) - ! subgrid hillslope hydrology constituents - integer, pointer :: ncolumns_hillslope(:) - ! whether we have urban to initialize in each grid cell ! (second dimension goes 1:numurbl) real(r8), pointer :: pct_urban_max(:,:) + ! subgrid hillslope hydrology constituents + integer, pointer :: ncolumns_hillslope(:) + !----------------------------------------------------------------------- end module clm_instur diff --git a/src/main/controlMod.F90 b/src/main/controlMod.F90 index dc9622ddac..46d9e9958a 100644 --- a/src/main/controlMod.F90 +++ b/src/main/controlMod.F90 @@ -279,6 +279,8 @@ subroutine control_init(dtime) ! All old cpp-ifdefs are below and have been converted to namelist variables + namelist /clm_inparm/ convert_ocean_to_land + ! Number of dominant pfts and landunits. Enhance ctsm performance by ! reducing the number of active pfts to n_dom_pfts and ! active landunits to n_dom_landunits. @@ -750,6 +752,7 @@ subroutine control_spmd() ! Other subgrid logic call mpi_bcast(run_zero_weight_urban, 1, MPI_LOGICAL, 0, mpicom, ier) call mpi_bcast(all_active, 1, MPI_LOGICAL, 0, mpicom, ier) + call mpi_bcast(convert_ocean_to_land, 1, MPI_LOGICAL, 0, mpicom, ier) ! Number of dominant pfts and landunits. Enhance ctsm performance by ! reducing the number of active pfts to n_dom_pfts and @@ -1002,6 +1005,7 @@ subroutine control_print () else write(iulog,*) ' land frac data = ',trim(fatmlndfrc) end if + write(iulog,*) ' Convert ocean to land = ', convert_ocean_to_land write(iulog,*) ' Number of ACTIVE PFTS (0 means input pft data NOT collapsed to n_dom_pfts) =', n_dom_pfts write(iulog,*) ' Number of ACTIVE LANDUNITS (0 means input landunit data NOT collapsed to n_dom_landunits) =', n_dom_landunits write(iulog,*) ' Collapse urban landunits; done before collapsing all landunits to n_dom_landunits; .false. means do nothing i.e. keep all the urban landunits, though n_dom_landunits may still remove them =', collapse_urban diff --git a/src/main/histFileMod.F90 b/src/main/histFileMod.F90 index 863bf6e987..80405335da 100644 --- a/src/main/histFileMod.F90 +++ b/src/main/histFileMod.F90 @@ -3504,17 +3504,6 @@ subroutine htape_timeconst(t, mode) long_name='land/ocean mask (0.=ocean and 1.=land)', ncid=nfid(t), & imissing_value=ispval, ifill_value=ispval) end if - if (ldomain%isgrid2d) then - call ncd_defvar(varname='pftmask' , xtype=ncd_int, & - dim1name='lon', dim2name='lat', & - long_name='pft real/fake mask (0.=fake and 1.=real)', ncid=nfid(t), & - imissing_value=ispval, ifill_value=ispval) - else - call ncd_defvar(varname='pftmask' , xtype=ncd_int, & - dim1name=grlnd, & - long_name='pft real/fake mask (0.=fake and 1.=real)', ncid=nfid(t), & - imissing_value=ispval, ifill_value=ispval) - end if if (ldomain%isgrid2d) then call ncd_defvar(varname='nbedrock' , xtype=ncd_int, & dim1name='lon', dim2name='lat', & @@ -3542,7 +3531,6 @@ subroutine htape_timeconst(t, mode) call ncd_io(varname='area' , data=ldomain%area, dim1name=grlnd, ncid=nfid(t), flag='write') call ncd_io(varname='landfrac', data=ldomain%frac, dim1name=grlnd, ncid=nfid(t), flag='write') call ncd_io(varname='landmask', data=ldomain%mask, dim1name=grlnd, ncid=nfid(t), flag='write') - call ncd_io(varname='pftmask' , data=ldomain%pftm, dim1name=grlnd, ncid=nfid(t), flag='write') call ncd_io(varname='nbedrock' , data=grc%nbedrock, dim1name=grlnd, ncid=nfid(t), flag='write') end if ! (define/write mode diff --git a/src/main/initVerticalMod.F90 b/src/main/initVerticalMod.F90 index e88c4e1a18..b91c3439aa 100644 --- a/src/main/initVerticalMod.F90 +++ b/src/main/initVerticalMod.F90 @@ -16,7 +16,7 @@ module initVerticalMod use clm_varpar , only : toplev_equalspace, nlev_equalspace use clm_varpar , only : nlevsoi, nlevsoifl, nlevurb, nlevmaxurbgrnd use clm_varctl , only : fsurdat, iulog - use clm_varctl , only : use_vancouver, use_mexicocity, use_extralakelayers + use clm_varctl , only : use_extralakelayers use clm_varctl , only : use_bedrock, rundef use clm_varctl , only : soil_layerstruct_predefined, soil_layerstruct_userdefined use clm_varctl , only : use_fates @@ -329,6 +329,11 @@ subroutine initVertical(bounds, glc_behavior, thick_wall, thick_roof) write(iulog, *) 'dzsoi_decomp: ',dzsoi_decomp end if + if (nlevurb == ispval) then + call shr_sys_abort(' ERROR nlevurb has not been defined '//& + errMsg(sourcefile, __LINE__)) + end if + if (nlevurb > 0) then allocate(zurb_wall(bounds%begl:bounds%endl,nlevurb), & zurb_roof(bounds%begl:bounds%endl,nlevurb), & @@ -349,122 +354,36 @@ subroutine initVertical(bounds, glc_behavior, thick_wall, thick_roof) ! "0" refers to urban wall/roof surface and "nlevsoi" refers to urban wall/roof bottom if (lun%urbpoi(l)) then - if (use_vancouver) then - zurb_wall(l,1) = 0.010_r8/2._r8 - zurb_wall(l,2) = zurb_wall(l,1) + 0.010_r8/2._r8 + 0.020_r8/2._r8 - zurb_wall(l,3) = zurb_wall(l,2) + 0.020_r8/2._r8 + 0.070_r8/2._r8 - zurb_wall(l,4) = zurb_wall(l,3) + 0.070_r8/2._r8 + 0.070_r8/2._r8 - zurb_wall(l,5) = zurb_wall(l,4) + 0.070_r8/2._r8 + 0.030_r8/2._r8 - - zurb_roof(l,1) = 0.010_r8/2._r8 - zurb_roof(l,2) = zurb_roof(l,1) + 0.010_r8/2._r8 + 0.010_r8/2._r8 - zurb_roof(l,3) = zurb_roof(l,2) + 0.010_r8/2._r8 + 0.010_r8/2._r8 - zurb_roof(l,4) = zurb_roof(l,3) + 0.010_r8/2._r8 + 0.010_r8/2._r8 - zurb_roof(l,5) = zurb_roof(l,4) + 0.010_r8/2._r8 + 0.030_r8/2._r8 - - dzurb_wall(l,1) = 0.010_r8 - dzurb_wall(l,2) = 0.020_r8 - dzurb_wall(l,3) = 0.070_r8 - dzurb_wall(l,4) = 0.070_r8 - dzurb_wall(l,5) = 0.030_r8 - write(iulog,*)'Total thickness of wall: ',sum(dzurb_wall(l,:)) - write(iulog,*)'Wall layer thicknesses: ',dzurb_wall(l,:) - - dzurb_roof(l,1) = 0.010_r8 - dzurb_roof(l,2) = 0.010_r8 - dzurb_roof(l,3) = 0.010_r8 - dzurb_roof(l,4) = 0.010_r8 - dzurb_roof(l,5) = 0.030_r8 - write(iulog,*)'Total thickness of roof: ',sum(dzurb_roof(l,:)) - write(iulog,*)'Roof layer thicknesses: ',dzurb_roof(l,:) - - ziurb_wall(l,0) = 0. - ziurb_wall(l,1) = dzurb_wall(l,1) - do j = 2,nlevurb - ziurb_wall(l,j) = sum(dzurb_wall(l,1:j)) - end do - write(iulog,*)'Wall layer interface depths: ',ziurb_wall(l,:) + do j = 1, nlevurb + zurb_wall(l,j) = (j-0.5)*(thick_wall(l)/float(nlevurb)) !node depths + end do + do j = 1, nlevurb + zurb_roof(l,j) = (j-0.5)*(thick_roof(l)/float(nlevurb)) !node depths + end do - ziurb_roof(l,0) = 0. - ziurb_roof(l,1) = dzurb_roof(l,1) - do j = 2,nlevurb - ziurb_roof(l,j) = sum(dzurb_roof(l,1:j)) - end do - write(iulog,*)'Roof layer interface depths: ',ziurb_roof(l,:) - else if (use_mexicocity) then - zurb_wall(l,1) = 0.015_r8/2._r8 - zurb_wall(l,2) = zurb_wall(l,1) + 0.015_r8/2._r8 + 0.120_r8/2._r8 - zurb_wall(l,3) = zurb_wall(l,2) + 0.120_r8/2._r8 + 0.150_r8/2._r8 - zurb_wall(l,4) = zurb_wall(l,3) + 0.150_r8/2._r8 + 0.150_r8/2._r8 - zurb_wall(l,5) = zurb_wall(l,4) + 0.150_r8/2._r8 + 0.015_r8/2._r8 - - zurb_roof(l,1) = 0.010_r8/2._r8 - zurb_roof(l,2) = zurb_roof(l,1) + 0.010_r8/2._r8 + 0.050_r8/2._r8 - zurb_roof(l,3) = zurb_roof(l,2) + 0.050_r8/2._r8 + 0.050_r8/2._r8 - zurb_roof(l,4) = zurb_roof(l,3) + 0.050_r8/2._r8 + 0.050_r8/2._r8 - zurb_roof(l,5) = zurb_roof(l,4) + 0.050_r8/2._r8 + 0.025_r8/2._r8 - - dzurb_wall(l,1) = 0.015_r8 - dzurb_wall(l,2) = 0.120_r8 - dzurb_wall(l,3) = 0.150_r8 - dzurb_wall(l,4) = 0.150_r8 - dzurb_wall(l,5) = 0.015_r8 - write(iulog,*)'Total thickness of wall: ',sum(dzurb_wall(l,:)) - write(iulog,*)'Wall layer thicknesses: ',dzurb_wall(l,:) - - dzurb_roof(l,1) = 0.010_r8 - dzurb_roof(l,2) = 0.050_r8 - dzurb_roof(l,3) = 0.050_r8 - dzurb_roof(l,4) = 0.050_r8 - dzurb_roof(l,5) = 0.025_r8 - write(iulog,*)'Total thickness of roof: ',sum(dzurb_roof(l,:)) - write(iulog,*)'Roof layer thicknesses: ',dzurb_roof(l,:) - - ziurb_wall(l,0) = 0. - ziurb_wall(l,1) = dzurb_wall(l,1) - do j = 2,nlevurb - ziurb_wall(l,j) = sum(dzurb_wall(l,1:j)) - end do - write(iulog,*)'Wall layer interface depths: ',ziurb_wall(l,:) + dzurb_roof(l,1) = 0.5*(zurb_roof(l,1)+zurb_roof(l,2)) !thickness b/n two interfaces + do j = 2,nlevurb-1 + dzurb_roof(l,j)= 0.5*(zurb_roof(l,j+1)-zurb_roof(l,j-1)) + enddo + dzurb_roof(l,nlevurb) = zurb_roof(l,nlevurb)-zurb_roof(l,nlevurb-1) - ziurb_roof(l,0) = 0. - ziurb_roof(l,1) = dzurb_roof(l,1) - do j = 2,nlevurb - ziurb_roof(l,j) = sum(dzurb_roof(l,1:j)) - end do - write(iulog,*)'Roof layer interface depths: ',ziurb_roof(l,:) - else - do j = 1, nlevurb - zurb_wall(l,j) = (j-0.5)*(thick_wall(l)/float(nlevurb)) !node depths - end do - do j = 1, nlevurb - zurb_roof(l,j) = (j-0.5)*(thick_roof(l)/float(nlevurb)) !node depths - end do + dzurb_wall(l,1) = 0.5*(zurb_wall(l,1)+zurb_wall(l,2)) !thickness b/n two interfaces + do j = 2,nlevurb-1 + dzurb_wall(l,j)= 0.5*(zurb_wall(l,j+1)-zurb_wall(l,j-1)) + enddo + dzurb_wall(l,nlevurb) = zurb_wall(l,nlevurb)-zurb_wall(l,nlevurb-1) - dzurb_roof(l,1) = 0.5*(zurb_roof(l,1)+zurb_roof(l,2)) !thickness b/n two interfaces - do j = 2,nlevurb-1 - dzurb_roof(l,j)= 0.5*(zurb_roof(l,j+1)-zurb_roof(l,j-1)) - enddo - dzurb_roof(l,nlevurb) = zurb_roof(l,nlevurb)-zurb_roof(l,nlevurb-1) - - dzurb_wall(l,1) = 0.5*(zurb_wall(l,1)+zurb_wall(l,2)) !thickness b/n two interfaces - do j = 2,nlevurb-1 - dzurb_wall(l,j)= 0.5*(zurb_wall(l,j+1)-zurb_wall(l,j-1)) - enddo - dzurb_wall(l,nlevurb) = zurb_wall(l,nlevurb)-zurb_wall(l,nlevurb-1) - - ziurb_wall(l,0) = 0. - do j = 1, nlevurb-1 - ziurb_wall(l,j) = 0.5*(zurb_wall(l,j)+zurb_wall(l,j+1)) !interface depths - enddo - ziurb_wall(l,nlevurb) = zurb_wall(l,nlevurb) + 0.5*dzurb_wall(l,nlevurb) - - ziurb_roof(l,0) = 0. - do j = 1, nlevurb-1 - ziurb_roof(l,j) = 0.5*(zurb_roof(l,j)+zurb_roof(l,j+1)) !interface depths - enddo - ziurb_roof(l,nlevurb) = zurb_roof(l,nlevurb) + 0.5*dzurb_roof(l,nlevurb) - end if + ziurb_wall(l,0) = 0. + do j = 1, nlevurb-1 + ziurb_wall(l,j) = 0.5*(zurb_wall(l,j)+zurb_wall(l,j+1)) !interface depths + enddo + ziurb_wall(l,nlevurb) = zurb_wall(l,nlevurb) + 0.5*dzurb_wall(l,nlevurb) + + ziurb_roof(l,0) = 0. + do j = 1, nlevurb-1 + ziurb_roof(l,j) = 0.5*(zurb_roof(l,j)+zurb_roof(l,j+1)) !interface depths + enddo + ziurb_roof(l,nlevurb) = zurb_roof(l,nlevurb) + 0.5*dzurb_roof(l,nlevurb) end if end do diff --git a/src/main/landunit_varcon.F90 b/src/main/landunit_varcon.F90 index 36eccb7001..001fe95a06 100644 --- a/src/main/landunit_varcon.F90 +++ b/src/main/landunit_varcon.F90 @@ -18,9 +18,7 @@ module landunit_varcon integer, parameter, public :: istsoil = 1 !soil landunit type (natural vegetation) integer, parameter, public :: istcrop = 2 !crop landunit type - ! Landunit 3 currently unused (used to be non-multiple elevation class glacier type: - ! istice, and landunit 4 was istice_mec; now they are combined into a single landunit - ! type, 4) + integer, parameter, public :: istocn = 3 !ocean landunit type integer, parameter, public :: istice = 4 !land ice landunit type integer, parameter, public :: istdlak = 5 !deep lake landunit type (now used for all lakes) integer, parameter, public :: istwet = 6 !wetland landunit type (swamp, marsh, etc.) @@ -118,7 +116,7 @@ subroutine set_landunit_names landunit_names(istsoil) = 'vegetated_or_bare_soil' landunit_names(istcrop) = 'crop' - landunit_names(istcrop+1) = unused + landunit_names(istocn) = 'ocean' landunit_names(istice) = 'landice' landunit_names(istdlak) = 'deep_lake' landunit_names(istwet) = 'wetland' diff --git a/src/main/subgridMod.F90 b/src/main/subgridMod.F90 index 4118ac73ed..b9a66e3064 100644 --- a/src/main/subgridMod.F90 +++ b/src/main/subgridMod.F90 @@ -583,11 +583,11 @@ function lake_landunit_exists(gi) result(exists) ! ! !DESCRIPTION: ! Returns true if a land unit for lakes should be created in memory - ! which is defined for gridcells which will grow lake, given by haslake + ! which is defined for gridcells which will grow lake, given by pct_lake_max ! ! !USES: use dynSubgridControlMod , only : get_do_transient_lakes - use clm_instur , only : haslake + use clm_instur , only : pct_lake_max ! ! !ARGUMENTS: logical :: exists ! function result @@ -599,10 +599,10 @@ function lake_landunit_exists(gi) result(exists) !----------------------------------------------------------------------- if (get_do_transient_lakes()) then - ! To support dynamic landunits, we initialise a lake land unit in each grid cell in which there are lakes. - ! This is defined by the haslake variable + ! To support dynamic landunits, we initialise a lake land unit in + ! each grid cell in which there are lakes as defined by pct_lake_max - if (haslake(gi)) then + if (pct_lake_max(gi) > 0._r8) then exists = .true. else exists = .false. diff --git a/src/main/subgridWeightsMod.F90 b/src/main/subgridWeightsMod.F90 index 94c7fec504..45e7d32306 100644 --- a/src/main/subgridWeightsMod.F90 +++ b/src/main/subgridWeightsMod.F90 @@ -696,6 +696,10 @@ subroutine check_weights (bounds, active_only) write(iulog,*) 'The matching input grid cell had some non-zero-weight subgrid type' write(iulog,*) 'that is not present in memory in the new run.' write(iulog,*) ' ' + write(iulog,*) 'If you are using a ctsm5.2 or later fsurdat file containing' + write(iulog,*) 'PCT_OCEAN > 0, then you may solve the error by setting' + write(iulog,*) 'convert_ocean_to_land = .true.' + write(iulog,*) ' ' call endrun(msg=errMsg(sourcefile, __LINE__)) end if diff --git a/src/main/surfrdMod.F90 b/src/main/surfrdMod.F90 index 03a0082e97..12212e2160 100644 --- a/src/main/surfrdMod.F90 +++ b/src/main/surfrdMod.F90 @@ -15,7 +15,7 @@ module surfrdMod use clm_varcon , only : grlnd use clm_varctl , only : iulog use clm_varctl , only : use_cndv, use_crop, use_fates - use surfrdUtilsMod , only : check_sums_equal_1, collapse_crop_types + use surfrdUtilsMod , only : check_sums_equal_1, apply_convert_ocean_to_land, collapse_crop_types use surfrdUtilsMod , only : collapse_to_dominant, collapse_crop_var, collapse_individual_lunits use ncdio_pio , only : file_desc_t, var_desc_t, ncd_pio_openfile, ncd_pio_closefile use ncdio_pio , only : ncd_io, check_var, ncd_inqfdims, check_dim_size, ncd_inqdid, ncd_inqdlen @@ -29,6 +29,7 @@ module surfrdMod ! !PUBLIC MEMBER FUNCTIONS: public :: surfrd_get_data ! Read surface dataset and determine subgrid weights public :: surfrd_get_num_patches ! Read surface dataset to determine maxsoil_patches and numcft + public :: surfrd_get_nlevurb ! Read surface dataset to determine nlevurb ! !PRIVATE MEMBER FUNCTIONS: private :: surfrd_special ! Read the special landunits @@ -69,7 +70,7 @@ subroutine surfrd_get_data (begg, endg, ldomain, lfsurdat, actual_numcft) ! o real % abundance PFTs (as a percent of vegetated area) ! ! !USES: - use clm_varctl , only : create_crop_landunit, collapse_urban, & + use clm_varctl , only : create_crop_landunit, convert_ocean_to_land, collapse_urban, & toosmall_soil, toosmall_crop, toosmall_glacier, & toosmall_lake, toosmall_wetland, toosmall_urban, & n_dom_landunits @@ -119,13 +120,6 @@ subroutine surfrd_get_data (begg, endg, ldomain, lfsurdat, actual_numcft) call getfil( lfsurdat, locfn, 0 ) call ncd_pio_openfile (ncid, trim(locfn), 0) - ! Read in patch mask - this variable is only on the surface dataset - but not - ! on the domain dataset - - call ncd_io(ncid=ncid, varname= 'PFTDATA_MASK', flag='read', data=ldomain%pftm, & - dim1name=grlnd, readvar=readvar) - if (.not. readvar) call endrun( msg=' ERROR: pftm NOT on surface dataset'//errMsg(sourcefile, __LINE__)) - ! Cmopare surfdat_domain attributes to ldomain attributes call check_var(ncid=ncid, varname='xc', readvar=readvar) @@ -199,6 +193,10 @@ subroutine surfrd_get_data (begg, endg, ldomain, lfsurdat, actual_numcft) call check_sums_equal_1(wt_lunit, begg, 'wt_lunit', subname) + if (convert_ocean_to_land) then + call apply_convert_ocean_to_land(wt_lunit(begg:endg,:), begg, endg) + end if + ! if collapse_urban = .true. ! collapse urban landunits to the dominant urban landunit @@ -321,6 +319,48 @@ subroutine surfrd_get_num_patches (lfsurdat, actual_maxsoil_patches, actual_nump end subroutine surfrd_get_num_patches +!----------------------------------------------------------------------- + subroutine surfrd_get_nlevurb (lfsurdat, actual_nlevurb) + ! + ! !DESCRIPTION: + ! Read nlevurb from the surface dataset + ! + ! !USES: + use fileutils , only : getfil + ! + ! !ARGUMENTS: + character(len=*), intent(in) :: lfsurdat ! surface dataset filename + integer, intent(out) :: actual_nlevurb ! nlevurb from surface dataset + ! + ! !LOCAL VARIABLES: + character(len=256):: locfn ! local file name + type(file_desc_t) :: ncid ! netcdf file id + integer :: dimid ! netCDF dimension id + character(len=32) :: subname = 'surfrd_get_nlevurb' ! subroutine name + !----------------------------------------------------------------------- + + if (masterproc) then + write(iulog,*) 'Attempting to read nlevurb from the surface data .....' + if (lfsurdat == ' ') then + write(iulog,*)'lfsurdat must be specified' + call endrun(msg=errMsg(sourcefile, __LINE__)) + endif + endif + + ! Open surface dataset + call getfil( lfsurdat, locfn, 0 ) + call ncd_pio_openfile (ncid, trim(locfn), 0) + + ! Read nlevurb + call ncd_inqdlen(ncid, dimid, actual_nlevurb, 'nlevurb') + + if ( masterproc )then + write(iulog,*) 'Successfully read nlevurb from the surface data' + write(iulog,*) + end if + + end subroutine surfrd_get_nlevurb + !----------------------------------------------------------------------- subroutine surfrd_special(begg, endg, ncid, ns) ! @@ -330,7 +370,7 @@ subroutine surfrd_special(begg, endg, ncid, ns) ! ! !USES: use clm_varpar , only : maxpatch_glc, nlevurb - use landunit_varcon , only : isturb_MIN, isturb_MAX, istdlak, istwet, istice + use landunit_varcon , only : isturb_MIN, isturb_MAX, istdlak, istwet, istice, istocn use clm_instur , only : wt_lunit, urban_valid, wt_glc_mec, topo_glc_mec use UrbanParamsType , only : CheckUrban ! @@ -350,6 +390,7 @@ subroutine surfrd_special(begg, endg, ncid, ns) real(r8),pointer :: pctgla(:) ! percent of grid cell is glacier real(r8),pointer :: pctlak(:) ! percent of grid cell is lake real(r8),pointer :: pctwet(:) ! percent of grid cell is wetland + real(r8),pointer :: pctocn(:) ! percent of grid cell is ocean real(r8),pointer :: pcturb(:,:) ! percent of grid cell is urbanized integer ,pointer :: urban_region_id(:) real(r8),pointer :: pcturb_tot(:) ! percent of grid cell is urban (sum over density classes) @@ -363,6 +404,7 @@ subroutine surfrd_special(begg, endg, ncid, ns) allocate(pctgla(begg:endg)) allocate(pctlak(begg:endg)) allocate(pctwet(begg:endg)) + allocate(pctocn(begg:endg)) allocate(pcturb(begg:endg,numurbl)) allocate(pcturb_tot(begg:endg)) allocate(urban_region_id(begg:endg)) @@ -372,6 +414,12 @@ subroutine surfrd_special(begg, endg, ncid, ns) ! Obtain non-grid surface properties of surface dataset other than percent patch + call ncd_io(ncid=ncid, varname='PCT_OCEAN', flag='read', data=pctocn, & + dim1name=grlnd, readvar=readvar) + if (.not. readvar) call endrun( msg= & + ' ERROR: PCT_OCEAN NOT on surfdata file but required when running ctsm5.2 or newer; ' // & + ' you are advised to generate a new surfdata file using the mksurfdata_esmf tool ' // errMsg(sourcefile, __LINE__)) + call ncd_io(ncid=ncid, varname='PCT_WETLAND', flag='read', data=pctwet, & dim1name=grlnd, readvar=readvar) if (.not. readvar) call endrun( msg=' ERROR: PCT_WETLAND NOT on surfdata file'//errMsg(sourcefile, __LINE__)) @@ -435,9 +483,9 @@ subroutine surfrd_special(begg, endg, ncid, ns) topo_glc_mec(:,:) = max(topo_glc_mec(:,:), 0._r8) - pctspec = pctwet + pctlak + pcturb_tot + pctgla + pctspec = pctwet + pctlak + pcturb_tot + pctgla + pctocn - ! Error check: glacier, lake, wetland, urban sum must be less than 100 + ! Error check: sum of glacier, lake, wetland, urban, ocean must be < 100 found = .false. do nl = begg,endg @@ -457,22 +505,25 @@ subroutine surfrd_special(begg, endg, ncid, ns) do nl = begg,endg - wt_lunit(nl,istdlak) = pctlak(nl)/100._r8 - - wt_lunit(nl,istwet) = pctwet(nl)/100._r8 + wt_lunit(nl,istdlak) = pctlak(nl) / 100._r8 - wt_lunit(nl,istice) = pctgla(nl)/100._r8 + ! Until ctsm5.1 we would label ocean points as wetland in fsurdat + ! files. Starting with ctsm5.2 we label ocean points as ocean + ! (always 100%) and wetland points as wetland. + wt_lunit(nl,istwet) = pctwet(nl) / 100._r8 + wt_lunit(nl,istocn) = pctocn(nl) / 100._r8 + wt_lunit(nl,istice) = pctgla(nl) / 100._r8 do n = isturb_MIN, isturb_MAX dens_index = n - isturb_MIN + 1 - wt_lunit(nl,n) = pcturb(nl,dens_index) / 100._r8 + wt_lunit(nl,n) = pcturb(nl,dens_index) / 100._r8 end do end do call CheckUrban(begg, endg, pcturb(begg:endg,:), subname) - deallocate(pctgla,pctlak,pctwet,pcturb,pcturb_tot,urban_region_id,pctspec) + deallocate(pctgla,pctlak,pctwet,pctocn,pcturb,pcturb_tot,urban_region_id,pctspec) end subroutine surfrd_special @@ -1005,7 +1056,7 @@ subroutine surfrd_lakemask(begg, endg) ! Necessary for the initialisation of the lake land units ! ! !USES: - use clm_instur , only : haslake + use clm_instur , only : pct_lake_max use dynSubgridControlMod , only : get_flanduse_timeseries use clm_varctl , only : fname_len use fileutils , only : getfil @@ -1041,9 +1092,9 @@ subroutine surfrd_lakemask(begg, endg) call ncd_pio_openfile (ncid_dynuse, trim(locfn), 0) ! read the lakemask - call ncd_io(ncid=ncid_dynuse, varname='HASLAKE' , flag='read', data=haslake, & + call ncd_io(ncid=ncid_dynuse, varname='PCT_LAKE_MAX' , flag='read', data=pct_lake_max, & dim1name=grlnd, readvar=readvar) - if (.not. readvar) call endrun( msg=' ERROR: HASLAKE is not on landuse.timeseries file'//errMsg(sourcefile, __LINE__)) + if (.not. readvar) call endrun( msg=' ERROR: PCT_LAKE_MAX is not on landuse.timeseries file'//errMsg(sourcefile, __LINE__)) ! close landuse_timeseries file again call ncd_pio_closefile(ncid_dynuse) diff --git a/src/main/surfrdUtilsMod.F90 b/src/main/surfrdUtilsMod.F90 index 97f5b7d80f..007770b3c3 100644 --- a/src/main/surfrdUtilsMod.F90 +++ b/src/main/surfrdUtilsMod.F90 @@ -21,7 +21,8 @@ module surfrdUtilsMod ! !PUBLIC MEMBER FUNCTIONS: public :: check_sums_equal_1 ! Confirm that sum(arr(n,:)) == 1 for all n public :: renormalize ! Renormalize an array - public :: convert_cft_to_pft ! Conversion of crop CFT to natural veg PFT:w + public :: apply_convert_ocean_to_land ! Apply the conversion of ocean to land points + public :: convert_cft_to_pft ! Conversion of crop CFT to natural veg PFT public :: collapse_crop_types ! Collapse unused crop types into types used in this run public :: collapse_individual_lunits ! Collapse landunits by user-defined thresholds public :: collapse_to_dominant ! Collapse to dominant pfts or landunits @@ -112,6 +113,40 @@ subroutine renormalize(arr, lb, normal) end subroutine renormalize + !----------------------------------------------------------------------- + subroutine apply_convert_ocean_to_land(wt_lunit, begg, endg) + ! + ! !DESCRIPTION: + ! Convert ocean points to land by changing ocean to natveg; + ! typically these points will become bare ground. + ! + ! Originally ocean points were assigned to wetland, so the motivation for + ! for this subroutine was to avoid the negative runoff that sometimes comes + ! from wetlands. + ! + ! !USES: + use landunit_varcon, only : istsoil, istocn, max_lunit + ! + ! !ARGUMENTS: + integer, intent(in) :: begg ! Beginning grid cell index + integer, intent(in) :: endg ! Ending grid cell index + ! This array is modified in-place: + real(r8), intent(inout) :: wt_lunit(begg:endg, max_lunit) ! Weights of landunits per grid cell + ! + ! !LOCAL VARIABLES: + integer :: g + + character(len=*), parameter :: subname = 'apply_convert_ocean_to_land' + !----------------------------------------------------------------------- + + do g = begg, endg + wt_lunit(g,istsoil) = wt_lunit(g,istsoil) + wt_lunit(g,istocn) + wt_lunit(g,istocn) = 0._r8 + end do + + end subroutine apply_convert_ocean_to_land + + !----------------------------------------------------------------------- subroutine convert_cft_to_pft( begg, endg, cftsize, wt_cft ) ! diff --git a/test/tools/README.testnames b/test/tools/README.testnames index f42864facc..983f883490 100644 --- a/test/tools/README.testnames +++ b/test/tools/README.testnames @@ -28,7 +28,7 @@ c -- mkprocdata_map d -- mkmapgrids e -- unused f -- unused -g -- mksurfdata_map +g -- unused h -- unused i -- tools scripts diff --git a/test/tools/input_tests_master b/test/tools/input_tests_master index 784df20ea5..3345aebbba 100644 --- a/test/tools/input_tests_master +++ b/test/tools/input_tests_master @@ -3,27 +3,6 @@ smc#4 TSMscript_tools.sh mkprocdata_map mkprocdata_map_wrap mkprocdata_ne30_to_f19_I2000^tools__ds blc#4 TBLscript_tools.sh mkprocdata_map mkprocdata_map_wrap mkprocdata_ne30_to_f19_I2000^tools__ds -smg54 TSMtools.sh mksurfdata_map tools__s namelist -blg54 TBLtools.sh mksurfdata_map tools__s namelist - -smi24 TSMscript_tools.sh mksurfdata_map mksurfdata.pl mksrfdt_T31_crpglc_2000^tools__ds -bli24 TBLscript_tools.sh mksurfdata_map mksurfdata.pl mksrfdt_T31_crpglc_2000^tools__ds - -smi04 TSMscript_tools.sh mksurfdata_map mksurfdata.pl mksrfdt_f09_PtVg^tools__ds -bli04 TBLscript_tools.sh mksurfdata_map mksurfdata.pl mksrfdt_f09_PtVg^tools__ds - -smi53 TSMscript_tools.sh mksurfdata_map mksurfdata.pl mksrfdt_10x15_1850^tools__o -bli53 TBLscript_tools.sh mksurfdata_map mksurfdata.pl mksrfdt_10x15_1850^tools__o -smi54 TSMscript_tools.sh mksurfdata_map mksurfdata.pl mksrfdt_10x15_1850^tools__ds -bli54 TBLscript_tools.sh mksurfdata_map mksurfdata.pl mksrfdt_10x15_1850^tools__ds -smi57 TSMscript_tools.sh mksurfdata_map mksurfdata.pl mksrfdt_10x15_1850^tools__do -bli57 TBLscript_tools.sh mksurfdata_map mksurfdata.pl mksrfdt_10x15_1850^tools__do -smi58 TSMscript_tools.sh mksurfdata_map mksurfdata.pl mksrfdt_10x15_crp_1850-2000^tools__do -bli58 TBLscript_tools.sh mksurfdata_map mksurfdata.pl mksrfdt_10x15_crp_1850-2000^tools__do - -smi64 TSMscript_tools.sh mksurfdata_map mksurfdata.pl mksrfdt_5x5_amazon_hirespft_2005^tools__ds -bli64 TBLscript_tools.sh mksurfdata_map mksurfdata.pl mksrfdt_5x5_amazon_hirespft_2005^tools__ds - sm0c1 TSMscript_tools.sh site_and_regional run_neon.py run_neon_OSBS bl0c1 TBLscript_tools.sh site_and_regional run_neon.py run_neon_OSBS sm0a1 TSMscript_tools.sh site_and_regional run_neon.py run_neon_YELL_PRISM @@ -42,8 +21,3 @@ blbd1 TBLscript_tools.sh site_and_regional subset_data subset_data_region1 smaa2 TSMscript_tools.sh site_and_regional modify_singlept_site_neon.py modify_data_YELL blaa2 TBLscript_tools.sh site_and_regional modify_singlept_site_neon.py modify_data_YELL - -smi#2 TSMscript_tools.sh mkmapdata mkmapdata.sh mkmapdata_ne30np4 -bli#2 TBLscript_tools.sh mkmapdata mkmapdata.sh mkmapdata_ne30np4 -smi59 TSMscript_tools.sh mkmapdata mkmapdata.sh mkmapdata_if10 -bli59 TBLscript_tools.sh mkmapdata mkmapdata.sh mkmapdata_if10 diff --git a/test/tools/nl_files/mksrfdt_10x15_1850 b/test/tools/nl_files/mksrfdt_10x15_1850 deleted file mode 100644 index cdbb7c13dc..0000000000 --- a/test/tools/nl_files/mksrfdt_10x15_1850 +++ /dev/null @@ -1 +0,0 @@ --l CSMDATA -vic -r 10x15 -no-crop -y 1850 -exedir EXEDIR diff --git a/test/tools/nl_files/mksrfdt_10x15_crp_1850-2000 b/test/tools/nl_files/mksrfdt_10x15_crp_1850-2000 deleted file mode 100644 index b42c1deb04..0000000000 --- a/test/tools/nl_files/mksrfdt_10x15_crp_1850-2000 +++ /dev/null @@ -1 +0,0 @@ --l CSMDATA -r 10x15 -y 1850-2000 -exedir EXEDIR diff --git a/test/tools/nl_files/mksrfdt_5x5_amazon_hirespft_2005 b/test/tools/nl_files/mksrfdt_5x5_amazon_hirespft_2005 deleted file mode 100644 index 47a5391c84..0000000000 --- a/test/tools/nl_files/mksrfdt_5x5_amazon_hirespft_2005 +++ /dev/null @@ -1 +0,0 @@ --l CSMDATA -r 5x5_amazon -y 2005 -hirespft -exedir EXEDIR diff --git a/test/tools/nl_files/mksrfdt_T31_crpglc_2000 b/test/tools/nl_files/mksrfdt_T31_crpglc_2000 deleted file mode 100644 index ac8ceed1a8..0000000000 --- a/test/tools/nl_files/mksrfdt_T31_crpglc_2000 +++ /dev/null @@ -1 +0,0 @@ --l CSMDATA -r 48x96 -y 2000 -glc_nec 10 -exedir EXEDIR diff --git a/test/tools/nl_files/mksrfdt_f09_PtVg b/test/tools/nl_files/mksrfdt_f09_PtVg deleted file mode 100644 index 61c2d8325e..0000000000 --- a/test/tools/nl_files/mksrfdt_f09_PtVg +++ /dev/null @@ -1 +0,0 @@ --l CSMDATA -r 0.9x1.25 -no-crop -y PtVg -exedir EXEDIR diff --git a/test/tools/nl_files/modify_data_YELL b/test/tools/nl_files/modify_data_YELL index 159c92ae63..0d180e8bf6 100644 --- a/test/tools/nl_files/modify_data_YELL +++ b/test/tools/nl_files/modify_data_YELL @@ -1 +1 @@ ---neon_site YELL --surf_dir CSMDATA/lnd/clm2/surfdata_map/NEON --out_dir EXEDIR --inputdata-dir CSMDATA +--neon_site YELL --surf_dir CSMDATA/lnd/clm2/surfdata_esmf/NEON --out_dir EXEDIR --inputdata-dir CSMDATA diff --git a/test/tools/tests_posttag_dav_mpi b/test/tools/tests_posttag_dav_mpi deleted file mode 100644 index ef42215791..0000000000 --- a/test/tools/tests_posttag_dav_mpi +++ /dev/null @@ -1,2 +0,0 @@ -smi#2 bli#2 -smi59 bli59 diff --git a/test/tools/tests_posttag_hobart_nompi b/test/tools/tests_posttag_hobart_nompi index d3cbccecdf..c185428868 100644 --- a/test/tools/tests_posttag_hobart_nompi +++ b/test/tools/tests_posttag_hobart_nompi @@ -1,3 +1 @@ smc#4 blc#4 -smi54 bli54 -smi57 bli57 diff --git a/test/tools/tests_posttag_izumi_nompi b/test/tools/tests_posttag_izumi_nompi deleted file mode 100644 index 3e84fb8459..0000000000 --- a/test/tools/tests_posttag_izumi_nompi +++ /dev/null @@ -1,2 +0,0 @@ -smi54 bli54 -smi57 bli57 diff --git a/test/tools/tests_posttag_nompi_regression b/test/tools/tests_posttag_nompi_regression index b665409c51..c185428868 100644 --- a/test/tools/tests_posttag_nompi_regression +++ b/test/tools/tests_posttag_nompi_regression @@ -1,7 +1 @@ smc#4 blc#4 -smg54 blg54 -smi24 bli24 -smi53 bli53 -smi54 bli54 -smi57 bli57 -smi58 bli58 diff --git a/test/tools/tests_pretag_cheyenne_nompi b/test/tools/tests_pretag_cheyenne_nompi index 6ce4972915..e92ffaaaad 100644 --- a/test/tools/tests_pretag_cheyenne_nompi +++ b/test/tools/tests_pretag_cheyenne_nompi @@ -1,11 +1,3 @@ smc#4 blc#4 -smg54 blg54 smba1 blba1 smbd1 blbd1 -smi04 bli04 -smi24 bli24 -smi53 bli53 -smi64 bli64 -smi54 bli54 -smi57 bli57 -smi58 bli58 diff --git a/tools/README b/tools/README index 2aaecc3bd8..568dc1239b 100644 --- a/tools/README +++ b/tools/README @@ -6,15 +6,13 @@ modification of CTSM input files. I. General directory structure: $CTSMROOT/tools - mksurfdata_map --- Create surface datasets. + mksurfdata_esmf -- Create surface datasets. crop_calendars --- Regrid and process GGCMI sowing and harvest date files for use in CTSM. - mkmapgrids ------- Create regular lat/lon SCRIP grid files needed by mkmapdata - mkmapdata -------- Create SCRIP mapping data from SCRIP grid files (uses ESMF) + mkmapgrids ------- Create regular lat/lon SCRIP grid files mkprocdata_map --- Convert output unstructured grids into a 2D format that can be plotted easily - ncl_scripts ------ NCL post or pre processing scripts. site_and_regional Scripts for handling input datasets for site and regional cases. These scripts both help with creation of datasets using the @@ -35,7 +33,7 @@ I. General directory structure: II. Notes on building/running for each of the above tools: - Each tool that has FORTRAN source code (mksurfdata_map and mkprocdata_map) has the following files: + mkprocdata_map has the following files to facilitate building the FORTRAN code: README ------- Specific help for using the specific tool and help on specific files in that directory. @@ -47,21 +45,6 @@ II. Notes on building/running for each of the above tools: src/Srcfiles ----- List of source files that are needed. src/Mkdepends ---- Dependency generator program - mkmapdata, mkmapgrids and ncl_scripts only contain scripts so don't have the above build files. - - Most tools have copies of files from other directories -- see the README.filecopies - file for more information on this. - - Tools may also have files with the directory name followed by namelist to provide sample namelists. - - .namelist ------ Namelist to create a global file. - - These files are also used by the test scripts to test the tools (see the - README.testing) file. - - NOTE: Be sure to change the path of the datasets references by these namelists to - point to where you have exported your CESM inputdata datasets. - To build: cd @@ -76,7 +59,7 @@ II. Notes on building/running for each of the above tools: so that you can use the debugger, and with bounds-checking, and float trapping on. To speed up do the following... - gmake OPT=TRUE (by default already on for mksurfdata_map) + gmake OPT=TRUE Also some of the tools allow for OpenMP shared memory parallelism (such as mksurfdata) with @@ -93,6 +76,28 @@ II. Notes on building/running for each of the above tools: run normally as above + mksurfdata_esmf has a cime configure and CMake based build using the following files: + + gen_mksurfdata_build ---- Build mksurfdata_esmf + src/CMakeLists.txt ------ Tells CMake how to build the source code + Makefile ---------------- GNU makefile to link the program together + cmake ------------------- CMake macros for finding libraries + + mkmapgrids, and site_and_regional only contain scripts so don't have the above build files. + + Some tools have copies of files from other directories -- see the README.filecopies + file for more information on this. + + Tools may also have files with the directory name followed by namelist to provide sample namelists. + + .namelist ------ Namelist to create a global file. + + These files are also used by the test scripts to test the tools (see the + README.testing) file. + + NOTE: Be sure to change the path of the datasets references by these namelists to + point to where you have exported your CESM inputdata datasets. + III. Process sequence to create input datasets needed to run CTSM 1.) Create SCRIP grid files (if needed) @@ -168,31 +173,10 @@ III. Process sequence to create input datasets needed to run CTSM http://www.cesm.ucar.edu/models/cesm1.0/clm/models/lnd/clm/doc/UsersGuide/book1.html - If you don't do this step, you'll need to specify the file to mkmapdata + If you don't do this step, you'll need to specify the file to mksurfdata_esmf in step (3) using the "-f" option. - 4.) Create mapping files for use by mksurfdata_map with mkmapdata - (See mkmapdata/README for more help on doing this) - - - this step uses the results of (1) that were entered into the XML database - by step (3). If you don't enter datasets in, you need to specify the - SCRIP grid file using the "-f" option to mkmapdata.sh. - - Example: to generate all necessary mapping files for the ne30np4 grid - - cd mkmapdata - ./mkmapdata.sh -r ne30np4 - - 5.) Add mapping file(s) created in step (4) into XML database in CTSM (optional) - - See notes on doing this in step (3) above. - Edit ../bld/namelist_files/namelist_defaults_clm.xml to incorporate new - mapping files. - - If you don't do this step, you'll need to specify the grid resolution name - and file creation dates to mksurfdata_map in step (5) below. - - 6.) Convert map of ocean to atm for use by DATM and CTSM with gen_domain + 4.) Convert map of ocean to atm for use by DATM and CTSM with gen_domain (See $CIMEROOT/tools/mapping/README for more help on doing this) - gen_domain uses the map from step (2) (or previously created CESM maps) @@ -213,72 +197,39 @@ III. Process sequence to create input datasets needed to run CTSM file for CTSM. Output domain files will be named according to the input OCN/LND gridnames. - 7.) Create surface datasets with mksurfdata_map - (See mksurfdata_map/README for more help on doing this) + 5.) Create surface datasets with mksurfdata_esmf on Derecho + (See mksurfdata_esmf/README.md for more help on doing this) + + - gen_mksurfdata_build to build + - gen_mksurfdata_namelist to build the namelist + - gen_mksurfdata_jobscript_single to build a batch script to run on Derecho + - Submit the batch script just created above - - Run mksurfdata_map/mksurfdata.pl - - This step uses the results of step (4) entered into the XML database - in step (5). + - This step uses the results of step (3) entered into the XML database + in step (4). - If datasets were NOT entered into the XML database, set the resolution - to "usrspec" and use the "-usr_gname", and "-usr_gdate" options. + by entering the mesh file using the options: --model-mesh --model-mesh-nx --model-mesh-ny - Example: for 0.9x1.25 resolution + Example: for 0.9x1.25 resolution fro 1850 - cd mksurfdata_map/src - gmake - cd .. - ./mksurfdata.pl -r 0.9x1.25 + cd mksurfdata_esmf + ./gen_mksurfdata_build + ./gen_mksurfdata_namelist --res 0.9x1.25 --start-year 1850 --end-year 1850 + ./gen_mksurfdata_jobscript_single --number-of-nodes 24 --tasks-per-node 12 --namelist-file target.namelist + qsub mksurfdata_jobscript_single.sh NOTE that surface dataset will be used by default for fatmgrid - and it will contain the lat,lon,edges and area values for the atm grid - ASSUMING that the atm and land grid are the same - 8.) Add new files to XML data or using user_nl_clm (optional) + 6.) Add new files to XML data or using user_nl_clm (optional) See notes on doing this in step (3) above. -IV. Example of creating single-point datasets without entering into XML database. - - Here we apply the process described in III. for a single-point dataset - where we don't enter the datasets into the XML database (thus skipping - steps 3, 5 and 8), but use the needed command line options to specify where the - files are. This also skips step (2) since step 1 creates the needed mapping file. - - 0.) Set name of grid to use and the creation date to be used later... - setenv GRIDNAME 1x1_boulderCO - setenv CDATE `date +%y%m%d` - 1.) SCRIP grid and atm to ocn mapping file - cd site_and_regional - ./mknoocnmap.pl -p 40,255 -n $GRIDNAME - # Set pointer to MAPFILE that will be used in step (6) - setenv MAPFILE `pwd`/map_${GRIDNAME}_noocean_to_${GRIDNAME}_nomask_aave_da_${CDATE}.nc - cd ../.. - 2.) skip - 3.) skip - 4.) Mapping files needed for mksurfdata_map - cd mkmapdata - setenv GRIDFILE ../mkmapgrids/SCRIPgrid_${GRIDNAME}_nomask_${CDATE}.nc - ./mkmapdata.sh -r $GRIDNAME -f $GRIDFILE -t regional - cd ../.. - 5.) skip - 6.) Generate domain file for datm and CTSM - cd $CIMEROOT/tools/mapping/gen_domain_files/src - gmake - cd .. - setenv OCNDOM domain.ocn_noocean.nc - setenv ATMDOM domain.lnd.{$GRIDNAME}_noocean.nc - ./gen_domain -m $MAPFILE -o $OCNDOM -l $ATMDOM - 7.) Create surface dataset for CTSM - cd mksurfdata_map/src - gmake - cd .. - ./mksurfdata.pl -r usrspec -usr_gname $GRIDNAME -usr_gdate $CDATE - 8.) skip - -V. Notes on which input datasets are needed for CTSM +IV. Notes on which input datasets are needed for CTSM global or regional/single-point grids - need fsurdata and fatmlndfrc - fsurdata ---- from mksurfdata_map in step (III.7) + fsurdata ---- from mksurfdata_esmf in step (III.7) fatmlndfrc -- use the domain.lnd file from gen_domain in step (III.6) diff --git a/tools/README.filecopies b/tools/README.filecopies index 5ab2bc96d1..a96dff1ab7 100644 --- a/tools/README.filecopies +++ b/tools/README.filecopies @@ -1,27 +1,20 @@ tools/README.filecopies May/26/2011 There are several files that are copies of the original files from -either CTSM src/main, cime/src/share/utils, -cime/src/share/unit_test_stubs, or copies from other tool -directories. By having copies the tools can all be made stand-alone, +either CTSM src/utils or src/main, or share/src. +By having copies the tools can all be made stand-alone, but any changes to the originals will have to be put into the tool directories as well. I. Files that are IDENTICAL: - 1. csm_share files copied that should be identical to cime/share/utils: + 1. csm_share files copied that should be identical to share/src: shr_kind_mod.F90 shr_const_mod.F90 - shr_log_mod.F90 - shr_timer_mod.F90 shr_string_mod.F90 shr_file_mod.F90 - 2. csm_share files copied that should be identical to cime/share/csm_share/unit_testers: - - test_mod.F90 - II. Files with differences 1. csm_share files copied with differences: @@ -32,7 +25,7 @@ II. Files with differences fileutils.F90 --- Remove use of masterproc and spmdMod and endrun in abortutils. - 3. Files in mksurfdata_map + 3. Files in mksurfdata_esmf mkvarpar.F90 nanMod.F90 diff --git a/tools/contrib/modify_singlept_site b/tools/contrib/modify_singlept_site index 46c1bcda1a..df89f6fb73 100755 --- a/tools/contrib/modify_singlept_site +++ b/tools/contrib/modify_singlept_site @@ -231,6 +231,7 @@ if create_surfdata: f2['PCT_WETLAND'] = 0. f2['PCT_URBAN'] = 0. f2['PCT_GLACIER'] = 0. + f2['PCT_OCEAN'] = 0. #-- Overwrite global data with raw data ---------------------------- f2['LONGXY'] = plon diff --git a/tools/contrib/run_clmtowers b/tools/contrib/run_clmtowers index 59b276260f..e4dd2519ff 100755 --- a/tools/contrib/run_clmtowers +++ b/tools/contrib/run_clmtowers @@ -48,13 +48,13 @@ else endif # Set location of your run directories -set rundata = /glade/scratch/oleson +set rundata = /glade/derecho/scratch/oleson # Set the location of your CLM tag set Clm_Tag_Dir = /glade/work/oleson/release-clm5.0.12 # Set the location of your surface datasets and shell commands that were generated by PTCLM. # This will not necessarily be in the same location as the CLM tag that you are running above -#set User_Mods_Dir = /glade/scratch/oleson/release-clm5.0.12 # This is my version for SP simulations -set User_Mods_Dir = /glade/scratch/oleson/release-clm5.0.12.BGC # This is my version for BGC simulations +#set User_Mods_Dir = /glade/derecho/scratch/oleson/release-clm5.0.12 # This is my version for SP simulations +set User_Mods_Dir = /glade/derecho/scratch/oleson/release-clm5.0.12.BGC # This is my version for BGC simulations # What sites to run? # These are the sites that can be evaluated with some combination of level 2 data and synthesis (gap-filled) data @@ -149,7 +149,7 @@ echo $sourcemods # Set some namelist options if required # If you set any of these you will need to also set them below (search on namelist_opts) -#set namelist_opts1 = "paramfile='/glade/p/cgd/tss/people/oleson/modify_param/CLM5_SP_ens_dec_5D_mcalib_psi50BET3_BETKr9_Cropkrmax5e-10_calmbboptleafcn.nc'" +#set namelist_opts1 = "paramfile='/glade/campaign/cgd/tss/people/oleson/modify_param/CLM5_SP_ens_dec_5D_mcalib_psi50BET3_BETKr9_Cropkrmax5e-10_calmbboptleafcn.nc'" #set namelist_opts2 = "baseflow_scalar= 0.001d00" # BGC #set namelist_opts3 = "pot_hmn_ign_counts_alpha= 0.012d00" diff --git a/tools/mkmapdata/README b/tools/mkmapdata/README deleted file mode 100644 index 77d89717ad..0000000000 --- a/tools/mkmapdata/README +++ /dev/null @@ -1,90 +0,0 @@ -$CTSMROOT/tools/mkmapdata/README Jun/08/2018 - -The routines in this directory create a mapping dataset from -SCRIP grid files to map from one grid to another. These mapping files -are used by either CLM or mksurfdata_map to regrid from one resolution -to another. - -We have generally moved to "nomask" grid and mapping files. These "nomask" -files typically contain mask and frac equal to 1 everywhere. During remapping -we now apply the source masks found in the raw datasets and ignore the -masks found in the mapping files. Exception: we continue to use a masked -grid file and mapping file to regrid the 1-km topography. - -The script uses ESMF and requires that ESMF be built and the path -for ESMF binary files (using the program ESMF_RegridWeightGen) -be given as input to the script. You need to build at least -two versions, one with mpiuni and one with mpi. Both versions -also need to be built with NetCDF rather than the default -IO version. - -Currently uses: ESMF7.1.0r - -Do the following for help with the different options to the script... - - ./mkmapdata.sh -help - -The following steps provide a method to create the executable -and generate the grid map dataset: - -0) Background tasks you only have to do once - - a.) Export the input SCRIP grid files for the resolutions you'll need - - Most of these files are on the Subversion inputdata server at... - - https://svn-ccsm-inputdata.cgd.ucar.edu/trunk/inputdata/lnd/clm2/mappingdata/grids/ - - Supported machines also have a copy on the CESM DIN_LOC_ROOT location - for that machine. - - b.) Obtain and build the versions of ESMF required for this script - -The version needs to support ESMF_RegridWeightGen and support the -options passed to it in the mkmapdata.sh script. As such it needs -to be built with NetCDF. You also need to build at least one -version with mpiuni and one with an mpi library. You also need -a version that supports the options: --netcdf4, --64bit_offset -and --src_type UGRID. - - http://www.earthsystemmodeling.org/ - -You may need more than one version to do everything above. On cheyenne -we use ESMF7.1.0r. - -The version of NetCDF used with ESMF needs to be version 4.1 or higher -and compiled with the NetCDF4 file format enabled (with HDF5 compression). -That will enable the --netcdf4 and --64bit_offset options to be used. - -1) cd to this directory - -2) Create map dataset(s) - Option A.) Use mkmapdata.sh directly - run script(e.g.): (see header of mkmapdata.sh for other environment that can be set) - - Example for standard resolutions - ./mkmapdata.sh -r 10x15 - Example for non-standard resolutions where you provide an input SCRIP grid file. - ./mkmapdata.sh -f - - Option B.) Alternatively, run regridbatch.sh to run mkmapdata.sh for a bunch of - different resolutions. - - Option C.) Alternatively, run mknoocnmap.pl to create a single-point/regional - map for an area without ocean (in the site_and_regional directory parallel to this one. - - ../site_and_regional/mknoocnmap.pl -help # for help on this script - -3) move (and rename if appropriate) generated map datasets - to $DIN_LOC_ROOT/lnd/clm/mappingdata/maps, etc. - - -Important files: - - regridbatch.sh ------- Script to run mkmapdata.sh for many resolutions on cheyenne - regriddav.sh --------- Script to run mkmapdata.sh for many resolutions on the DAV cluster (Casper) - mvNimport.sh --------- Script to copy and import mapping files in for many resolutions - mkmapdata.sh --------- Script to create mapping datasets for a given resolution - - rmdups.ncl ----------- NCL script to remove duplicate mapping points - diff --git a/tools/mkmapdata/createXMLEntries.pl b/tools/mkmapdata/createXMLEntries.pl deleted file mode 100755 index c65e6888f7..0000000000 --- a/tools/mkmapdata/createXMLEntries.pl +++ /dev/null @@ -1,116 +0,0 @@ -#!/usr/bin/env perl - -# Creates a file giving XML entries for all the mapping files in the -# current directory (mapping_entries.txt). Also creates another file -# giving commands to move these files to the inputdata space -# (mv_cmds.sh). -# -# Should be run with no arguments. -# -# See also bld/namelist_files/createMapEntry.pl, and mvNimport.sh in -# the current directory for scripts that share some of the -# functionality of this script. - -# Bill Sacks -# March, 2013 - -use strict; - -# ---------------------------------------------------------------------- -# FUNCTIONS -# ---------------------------------------------------------------------- - -# Given a map filename, returns a hash giving the resolutions and -# masks implicit in that filename. -# Inputs: -# - filename -# Output: -# - hash containing: -# - filename -# - from_res -# - from_mask -# - to_res -# - to_mask -# Or does a bare return if the filename doesn't match the expected pattern -sub get_resolutions_and_masks { - my $filename = shift; - - # The following match assumes that the destination mask is - # "nomask". This match will tolerate underscores in the - # destination grid (e.g., 5x5_amazon), but be careful about - # underscores in the source grid or source mask! - if ($filename =~ m/^map_(.*)_(.*)_to_(.*)_nomask/) { - my $from_res=$1; - my $from_mask=$2; - my $to_res=$3; - my $to_mask="nomask"; - - my %info = (filename => $filename, - from_res => $from_res, - from_mask => $from_mask, - to_res => $to_res, - to_mask => $to_mask); - - return %info; - } - else { - return; - } -} - - -# ---------------------------------------------------------------------- -# PARAMETERS DEFINED HERE -# ---------------------------------------------------------------------- - -my $CSMDATA = "/glade/p/cesm/cseg/inputdata"; -my $maps_dir = "lnd/clm2/mappingdata/maps"; # directory where mapping files are stored within the inputdata directory - -# ---------------------------------------------------------------------- -# BEGIN MAIN PROGRAM -# ---------------------------------------------------------------------- - -my @files = glob "map*.nc"; - -# Make a hash containing all of the files at each destination resolution. -# The keys of the hash are destination resolutions; the values are -# references to arrays of hash references, where these low-level -# hashes are the return values of get_resolutions_and_masks. -my %dest_resols; -foreach my $file (@files) { - my %info = get_resolutions_and_masks($file); - if (%info) { - my $to_res = $info{'to_res'}; - push @{$dest_resols{$to_res}}, \%info; - } - else { - warn "WARNING: $file doesn't match expected mapping filename pattern; skipping\n"; - } -} - -open MAP_ENTRIES, ">", "mapping_entries.txt"; -open MV_CMDS, ">", "mv_cmds.sh"; - -# Output xml entries (and mv commands) grouped by destination resolution -foreach my $to_res (sort keys %dest_resols) { - my $full_maps_dir = "$maps_dir/$to_res"; - - foreach my $info_ref (@{$dest_resols{$to_res}}) { - my $filename = ${$info_ref}{'filename'}; - my $from_res = ${$info_ref}{'from_res'}; - my $from_mask = ${$info_ref}{'from_mask'}; - my $to_res = ${$info_ref}{'to_res'}; - my $to_mask = ${$info_ref}{'to_mask'}; - - print MV_CMDS "mv $filename $CSMDATA/$full_maps_dir/$filename\n"; - print MAP_ENTRIES "$full_maps_dir/$filename\n"; - } - - # Print blank line between destination grids - print MAP_ENTRIES "\n"; -} - -system "chmod", "755", "mv_cmds.sh"; -close MAP_ENTRIES; -close MV_CMDS; diff --git a/tools/mkmapdata/mkmapdata.sh b/tools/mkmapdata/mkmapdata.sh deleted file mode 100755 index 77f64956bd..0000000000 --- a/tools/mkmapdata/mkmapdata.sh +++ /dev/null @@ -1,594 +0,0 @@ -#!/bin/bash -set -e -#---------------------------------------------------------------------- -# -# mkmapdata.sh -# -# Create needed mapping files for mksurfdata_map and CLM. -# -# Example to run for an output resolution of 4x5 -# -# mkmapdata.sh -r 4x5 -# -# valid arguments: -# -f Input grid filename -# -t Output type, supported values are [regional, global] -# -r Output resolution -# -b use batch mode (not default) -# -i High resolution mode (Only used with -f) -# -l list mapping files required (so can use check_input_data to get them) -# -d debug usage -- display mkmapdata that will be run but don't execute them -# -v verbose usage -- log more information on what is happening -# -h displays this help message -# -# You can also set the following env variables: -# -# ESMFBIN_PATH - Path to ESMF binaries -# CSMDATA ------ Path to CESM input data -# MPIEXEC ------ Name of mpirun executable -# REGRID_PROC -- Number of MPI processors to use -# -#---------------------------------------------------------------------- -echo $0 -dir=${0%/*} -if [ "$dir" = "$0" ];then - dir="." -fi -outfilelist="clm.input_data_list" -default_res="10x15" - -#---------------------------------------------------------------------- -# SET SOME DEFAULTS -- if not set via env variables outside - -hostname=`hostname` -case $hostname in - - ##cheyenne - cheyenne* | r* ) - if [ -z "$CSMDATA" ]; then - CSMDATA=/glade/p/cesm/cseg/inputdata - fi - ;; - - ##casper - casper* | crthc* ) - if [ -z "$CSMDATA" ]; then - CSMDATA=/glade/p/cesm/cseg/inputdata - fi - ;; - - ##hobart/izumi/thorodin - hobart* | izumi* | thorodin* ) - if [ -z "$CSMDATA" ]; then - CSMDATA=/fs/cgd/csm/inputdata - fi - ;; - -esac - -if [[ -z ${CSMDATA} ]]; then - echo "CSMDATA path not known for host ${hostname}. Set manually before calling mkmapdata.sh. E.g., bash: export CSMDATA=/path/to/csmdata" - exit 7 -elif [[ ! -d "${CSMDATA}" ]]; then - echo "CSMDATA not found: ${CSMDATA}" - exit 8 -fi - -#---------------------------------------------------------------------- -# Usage subroutine -usage() { - echo "" - echo "**********************" - echo "usage:" - echo "./mkmapdata.sh" - echo "" - echo "valid arguments: " - echo "[-f|--gridfile ] " - echo " Full pathname of model SCRIP grid file to use " - echo " This variable should be set if this is not a supported grid" - echo " This variable will override the automatic generation of the" - echo " filename generated from the -res argument " - echo " the filename is generated ASSUMING that this is a supported " - echo " grid that has entries in the file namelist_defaults_ctsm.xml" - echo " the -r|--res argument MUST be specied if this argument is specified" - echo "[-r|--res ]" - echo " Model output resolution (default is $default_res)" - echo "[-t|--gridtype ]" - echo " Model output grid type" - echo " supported values are [regional,global], (default is global)" - echo "[-b|--batch]" - echo " Toggles batch mode usage (and run with mpi). If you want to run in batch mode" - echo " you need to have a separate batch script for a supported machine" - echo " that calls this script interactively - you cannot submit this" - echo " script directly to the batch system" - echo "[-i|--hires]" - echo " Output maps are high resolution and large file support should be used" - echo "[-l|--list]" - echo " List mapping files required (use check_input_data to get them)" - echo " also writes data to $outfilelist" - echo "[-d|--debug]" - echo " Toggles debug-only (don't actually run mkmapdata just echo what would happen)" - echo "[-h|--help] " - echo " Displays this help message" - echo "[-v|--verbose]" - echo " Toggle verbose usage -- log more information on what is happening " - echo "[--fast]" - echo " Toggle fast maps only -- only create the maps that can be done quickly " - echo "" - echo " You can also set the following env variables:" - echo " ESMFBIN_PATH - Path to ESMF binaries " - echo " (default is determined by machine running on)" - echo " CSMDATA ------ Path to CESM input data" - echo " (default is $CSMDATA)" - echo " MPIEXEC ------ Name of mpirun executable" - echo " (default is determined by machine running on)" - echo " REGRID_PROC -- Number of MPI processors to use" - echo " (default is $REGRID_PROC)" - echo "" - echo "**defaults can be determined on the machines: cheyenne or casper" - echo "" - echo "**pass environment variables by preceding above commands " - echo " with 'env var1=setting var2=setting '" - echo "**********************" -} -#---------------------------------------------------------------------- -# runcmd subroutine -#---------------------------------------------------------------------- - -runcmd() { - cmd=$@ - if [ -z "$cmd" ]; then - echo "No command given to the runcmd function" - exit 3 - fi - if [ "$verbose" = "YES" ]; then - echo "$cmd" - fi - if [ "$debug" != "YES" ]; then - ${cmd} - rc=$? - else - rc=0 - fi - if [ $rc != 0 ]; then - echo "Error status returned from mkmapdata script" - exit 4 -undo - fi - return 0 -} - -#---------------------------------------------------------------------- -# Process input arguments -#---------------------------------------------------------------------- - -interactive="YES" -debug="no" -res="default" -type="global" -phys="clm4_5" -verbose="no" -list="no" -outgrid="" -gridfile="default" -fast="no" -netcdfout="none" - -while [ $# -gt 0 ]; do - case $1 in - -v|-V) - verbose="YES" - ;; - -b|--batch) - interactive="NO" - ;; - -d|--debug) - debug="YES" - ;; - --fast) - fast="YES" - ;; - -i|--hires) - netcdfout="64bit_offset" - ;; - -l|--list) - debug="YES" - list="YES" - ;; - -r|--res) - res=$2 - shift - ;; - -f|--gridfile) - gridfile=$2 - shift - ;; - -t|--gridtype) - type=$2 - shift - ;; - -h|--help ) - usage - exit 0 - ;; - * ) - echo "ERROR:: invalid argument sent in: $2" - usage - exit 1 - ;; - esac - shift -done - -echo "Script to create mapping files required by mksurfdata_map" - -#---------------------------------------------------------------------- -# Determine output scrip grid file -#---------------------------------------------------------------------- - -# Set general query command used below -QUERY="$dir/../../bld/queryDefaultNamelist.pl -silent -namelist clmexp " -QUERY="$QUERY -justvalue -options sim_year=2000 -csmdata $CSMDATA" -echo "query command is $QUERY" - -echo "" -DST_EXTRA_ARGS="" -if [ "$gridfile" != "default" ]; then - GRIDFILE=$gridfile - echo "Using user specified scrip grid file: $GRIDFILE" - if [ "$res" = "default" ]; then - echo "When user specified grid file is given you MUST set the resolution (as the name of your grid)\n"; - exit 1 - fi - - # For now, maked the assumption about user-specified grids -- - # that they are SCRIP format. In the future we may want to - # provide a command-line options to allow the user to - # override that default. - DST_LRGFIL=$netcdfout - DST_TYPE="SCRIP" -else - if [ "$res" = "default" ]; then - res=$default_res - fi - - QUERYARGS="-res $res -options lmask=nomask" - - # Find the output grid file for this resolution using the XML database - QUERYFIL="$QUERY -var scripgriddata $QUERYARGS -onlyfiles" - if [ "$verbose" = "YES" ]; then - echo $QUERYFIL - fi - GRIDFILE=`$QUERYFIL` - echo "Using default scrip grid file: $GRIDFILE" - - # Determine extra information about the destination grid file - DST_LRGFIL=`$QUERY -var scripgriddata_lrgfile_needed $QUERYARGS` - DST_TYPE=`$QUERY -var scripgriddata_type $QUERYARGS` - if [ "$DST_TYPE" = "UGRID" ]; then - # For UGRID, we need extra information: the meshname variable - dst_meshname=`$QUERY -var scripgriddata_meshname $QUERYARGS` - DST_EXTRA_ARGS="$DST_EXTRA_ARGS --dst_meshname $dst_meshname" - fi -fi - -if [ "$type" = "global" ] && [ `echo "$res" | grep -c "1x1_"` = 1 ]; then - echo "This is a regional resolution and yet it is being run as global, set type with '-t' option\n"; - exit 1 -fi -if [ "$type" = "global" ] && [ `echo "$res" | grep -c "5x5_"` = 1 ]; then - echo "This is a regional resolution and yet it is being run as global, set type with '-t' option\n"; - exit 1 -fi -echo "Output grid resolution is $res" -if [ -z "$GRIDFILE" ]; then - echo "Output grid file was NOT found for this resolution: $res\n"; - exit 1 -fi - -if [ "$list" = "YES" ]; then - echo "outgrid = $GRIDFILE" - echo "outgrid = $GRIDFILE" > $outfilelist -elif [ ! -f "$GRIDFILE" ]; then - echo "Input SCRIP grid file does NOT exist: $GRIDFILE\n"; - echo "Make sure CSMDATA environment variable is set correctly" - exit 1 -fi - -#---------------------------------------------------------------------- -# Determine all input grid files and output file names -#---------------------------------------------------------------------- - -if [ "$phys" = "clm4_5" ]; then - grids=( \ - "0.5x0.5_nomask" \ - "0.25x0.25_nomask" \ - "0.125x0.125_nomask" \ - "3x3min_nomask" \ - "5x5min_nomask" \ - "10x10min_nomask" \ - "0.9x1.25_nomask" \ - "1km-merge-10min_HYDRO1K-merge-nomask" \ - ) - -else - echo "ERROR: Unknown value for phys: $phys" - exit 1 -fi - -# Set timestamp for names below -# The flag `-d "-0 days"` can serve as a time saver as follows: -# If the script aborted without creating all of the map_ files and -# the user resubmits to create the remaining files on the next day, -# the user could change -0 to -1 to prevent the script from -# duplicating files already generated the day before. -# -CDATE="c"`date -d "-0 days" +%y%m%d` - -# Set name of each output mapping file -# First determine the name of the input scrip grid file -# for each of the above grids -declare -i nfile=1 -for gridmask in ${grids[*]} -do - grid=${gridmask%_*} - lmask=${gridmask#*_} - - QUERYARGS="-res $grid -options lmask=$lmask,glc_nec=10 " - - QUERYFIL="$QUERY -var scripgriddata $QUERYARGS -onlyfiles" - if [ "$verbose" = "YES" ]; then - echo $QUERYFIL - fi - INGRID[nfile]=`$QUERYFIL` - if [ "$list" = "YES" ]; then - echo "ingrid = ${INGRID[nfile]}" - echo "ingrid = ${INGRID[nfile]}" >> $outfilelist - fi - - OUTFILE[nfile]=map_${grid}_${lmask}_to_${res}_nomask_aave_da_$CDATE.nc - - # Determine extra information about the source grid file - SRC_EXTRA_ARGS[nfile]="" - SRC_LRGFIL[nfile]=`$QUERY -var scripgriddata_lrgfile_needed $QUERYARGS` - SRC_TYPE[nfile]=`$QUERY -var scripgriddata_type $QUERYARGS` - if [ "${SRC_TYPE[nfile]}" = "UGRID" ]; then - # For UGRID, we need extra information: the meshname variable - src_meshname=`$QUERY -var scripgriddata_meshname $QUERYARGS` - SRC_EXTRA_ARGS[nfile]="${SRC_EXTRA_ARGS[nfile]} --src_meshname $src_meshname" - fi - - nfile=nfile+1 -done - -#---------------------------------------------------------------------- -# Determine supported machine specific stuff -#---------------------------------------------------------------------- - -if [ -n "$NERSC_HOST" ]; then - hostname=$NERSC_HOST -fi -echo "Hostname = $hostname" -case $hostname in - ##cheyenne - cheyenne* | r* ) - . /glade/u/apps/ch/opt/lmod/8.1.7/lmod/lmod/init/bash - if [ -z "$REGRID_PROC" ]; then - REGRID_PROC=36 - fi - if [ interactive = "YES" ]; then - REGRID_PROC=1 - fi - if [ "$verbose" = "YES" ]; then - echo "Number of processors to regrid with = $REGRID_PROC" - fi - esmfvers=8.2.0b13 - intelvers=19.1.1 - module purge - module load intel/$intelvers -# module load esmf_libs -# module load esmf_libs/$esmfvers - module load nco - - if [[ $REGRID_PROC > 1 ]]; then - mpi=mpt - module load mpt/2.22 - else - mpi=mpiuni - fi -# module load esmf-${esmfvers}-ncdfio-${mpi}-O - module use /glade/p/cesmdata/cseg/PROGS/modulefiles/esmfpkgs/intel/$intelvers - module load esmf-${esmfvers}-ncdfio-${mpi}-g - if [ -z "$ESMFBIN_PATH" ]; then - ESMFBIN_PATH=`grep ESMF_APPSDIR $ESMFMKFILE | awk -F= '{print $2}'` - fi - if [ -z "$MPIEXEC" ]; then - MPIEXEC="mpiexec_mpt -np $REGRID_PROC" - fi - if [ "$verbose" = "YES" ]; then - echo "list of modules" - module list - fi - ;; - - ## Casper - casper* | crthc* ) - . /glade/u/apps/dav/opt/lmod/8.1.7/lmod/8.1.7/init/bash - if [ -z "$REGRID_PROC" ]; then - REGRID_PROC=8 - fi - if [ interactive = "YES" ]; then - REGRID_PROC=1 - fi - echo "REGRID_PROC=$REGRID_PROC" - esmfvers=7.1.0r - intelvers=17.0.1 - module purge - module load intel/$intelvers - if [ $? != 0 ]; then - echo "Error doing module load: intel/$intelvers" - exit 1 - fi - module load nco - module load netcdf - module load ncarcompilers - - module load esmflibs/$esmfvers - if [ $? != 0 ]; then - echo "Error doing module load: esmflibs/$esmfvers" - exit 1 - fi - - if [[ $REGRID_PROC > 1 ]]; then - mpi=mpi - echo "MPI option is NOT currently available" - exit 1 - else - mpi=uni - fi - module load esmf-${esmfvers}-ncdfio-${mpi}-O - if [ $? != 0 ]; then - echo "Error doing module load: esmf-${esmfvers}-ncdfio-${mpi}-O" - exit 1 - fi - if [ -z "$ESMFBIN_PATH" ]; then - ESMFBIN_PATH=`grep ESMF_APPSDIR $ESMFMKFILE | awk -F= '{print $2}'` - fi - echo "ESMFMKFILE: $ESMFMKFILE" - echo "LD_LIBRARY_PATH: $LD_LIBRARY_PATH" - - if [ -z "$MPIEXEC" ]; then - MPIEXEC="mpiexec -n $REGRID_PROC" - fi - ;; - - ##no other machine currently supported - *) - echo "Machine $hostname NOT recognized" - ;; - -esac - -# Error checks -if [ ! -d "$ESMFBIN_PATH" ]; then - echo "Path to ESMF binary directory does NOT exist: $ESMFBIN_PATH" - echo "Set the environment variable: ESMFBIN_PATH" - exit 1 -fi - -#---------------------------------------------------------------------- -# Generate the mapping files needed for surface dataset generation -#---------------------------------------------------------------------- - -# Resolve interactive or batch mode command -# NOTE - if you want to run in batch mode - you need to have a separate -# batch file that calls this script interactively - you cannot submit -# this script to the batch system - -if [ "$interactive" = "NO" ]; then - echo "Running in batch mode using MPI" - if [ -z "$MPIEXEC" ]; then - echo "Name of MPI exec to use was NOT set" - echo "Set the environment variable: MPIEXEC" - exit 1 - fi - if [ ! -x `which ${MPIEXEC%% *}` ]; then - echo "The MPIEXEC pathname given is NOT an executable: ${MPIEXEC%% *}" - echo "Set the environment variable: MPIEXEC or run in interactive mode without MPI" - exit 1 - fi - mpirun=$MPIEXEC - echo "Running in batch mode" -else - mpirun="" -fi - -ESMF_REGRID="$ESMFBIN_PATH/ESMF_RegridWeightGen" -if [ ! -x "$ESMF_REGRID" ]; then - echo "ESMF_RegridWeightGen does NOT exist in ESMF binary directory: $ESMFBIN_PATH\n" - echo "Upgrade to a newer version of ESMF with this utility included" - echo "Set the environment variable: ESMFBIN_PATH" - exit 1 -fi - -# Remove previous log files, if any -rm PET*.Log ||: - -# -# Now run the mapping for each file, checking that input files exist -# and then afterwards that the output mapping file exists -# -declare -i nfile=1 -until ((nfile>${#INGRID[*]})); do - echo "Creating mapping file: ${OUTFILE[nfile]}" - echo "From input grid: ${INGRID[nfile]}" - echo "For output grid: $GRIDFILE" - echo " " - if [ -z "${INGRID[nfile]}" ] || [ -z "$GRIDFILE" ] || [ -z "${OUTFILE[nfile]}" ]; then - echo "Either input or output grid or output mapping file is NOT set" - exit 3 - fi - if [ ! -f "${INGRID[nfile]}" ]; then - echo "Input grid file does NOT exist: ${INGRID[nfile]}" - if [ ! "$list" = "YES" ]; then - exit 2 - fi - fi - if [ ! -f "$GRIDFILE" ]; then - echo "Output grid file does NOT exist: $GRIDFILE" - exit 3 - fi - - # Determine what (if any) large file support is needed. Use the - # most extreme large file support needed by either the source file - # or the destination file. - if [ "$DST_LRGFIL" = "netcdf4" ] || [ "${SRC_LRGFIL[nfile]}" = "netcdf4" ]; then - lrgfil="--netcdf4" - elif [ "$DST_LRGFIL" = "64bit_offset" ] || [ "${SRC_LRGFIL[nfile]}" = "64bit_offset" ]; then - lrgfil="--64bit_offset" - elif [ "$DST_LRGFIL" = "none" ] && [ "${SRC_LRGFIL[nfile]}" = "none" ]; then - lrgfil="" - else - echo "Unknown LRGFIL type:" - echo "DST_LRGFIL = $DST_LRGFIL" - echo "SRC_LRGFIL = ${SRC_LRGFIL[nfile]}" - exit 4 - fi - - # Skip if file already exists - if [ -f "${OUTFILE[nfile]}" ]; then - echo "Skipping creation of ${OUTFILE[nfile]} as already exists" - # Skip if large file and Fast mode is on - elif [ "$fast" = "YES" ] && [ "${SRC_LRGFIL[nfile]}" = "netcdf4" ]; then - echo "Skipping creation of ${OUTFILE[nfile]} as fast mode is on so skipping large files in NetCDF4 format" - else - - cmd="$mpirun $ESMF_REGRID --ignore_unmapped -s ${INGRID[nfile]} " - cmd="$cmd -d $GRIDFILE -m conserve -w ${OUTFILE[nfile]}" - if [ $type = "regional" ]; then - cmd="$cmd --dst_regional" - fi - - cmd="$cmd --src_type ${SRC_TYPE[nfile]} ${SRC_EXTRA_ARGS[nfile]} --dst_type $DST_TYPE $DST_EXTRA_ARGS" - cmd="$cmd $lrgfil" - - runcmd $cmd - - if [ "$debug" != "YES" ] && [ ! -f "${OUTFILE[nfile]}" ]; then - echo "Output mapping file was NOT created: ${OUTFILE[nfile]}" - exit 6 - fi - # add some metadata to the file - HOST=`hostname` - history="$ESMF_REGRID" - runcmd "ncatted -a history,global,a,c,"$history" ${OUTFILE[nfile]}" - runcmd "ncatted -a hostname,global,a,c,$HOST -h ${OUTFILE[nfile]}" - runcmd "ncatted -a logname,global,a,c,$LOGNAME -h ${OUTFILE[nfile]}" - fi - - nfile=nfile+1 -done - -echo "Successfully created needed mapping files for $res" - -exit 0 diff --git a/tools/mkmapdata/mvNimport.sh b/tools/mkmapdata/mvNimport.sh deleted file mode 100755 index 184a3fac25..0000000000 --- a/tools/mkmapdata/mvNimport.sh +++ /dev/null @@ -1,75 +0,0 @@ -#!/bin/bash -# -# -# Batch script to move and import mapping files to inputdata -# for several resolutions. -# - -#---------------------------------------------------------------------- - -if [ -z "$CSMDATA" ]; then - CSMDATA=/fis/cgd/cseg/csm/inputdata -fi - -if [ ! -d "$CSMDATA" ]; then - echo "Environment variable CSMDATA is not set to a valid directory!" - exit 1 -fi - -mapdir="lnd/clm2/mappingdata/maps" -if [ ! -d "$CSMDATA/$mapdir" ]; then - echo "Environment variable CSMDATA is not set to a valid inputdata directory!" - exit 1 -fi - -if [ -z "$SVN_INP_DIR" ]; then - SVN_INP_DIR=https://svn-ccsm-inputdata.cgd.ucar.edu/trunk/inputdata -fi - -if [ $# -gt 0 ]; then - resols="" - for arg in $@; do - resols="$resols $arg" - done -else - echo "Run for all valid resolutions" - resols=`../bld/queryDefaultNamelist.pl -res list -silent` -fi -echo "Move and import mapping files for this list of resolutions: $resols" - -#---------------------------------------------------------------------- - -for res in $resols; do - echo "Move and import mapping files for: $res" - dir=$mapdir/$res - #---------------------------------------------------------------------- - files=(map_*${res}*_aave_da_c??????.nc) - if [ ${#files[*]} -lt 2 ]; then - echo "No mappingfiles found for $res" - exit 2 - else - if [ ! -d "$CSMDATA/$dir" ]; then - echo "Create mapping directory: $CSMDATA/$dir" - mkdir $CSMDATA/$dir - svn mkdir $SVN_INP_URL/$dir -m "Create mapping directory for $res" - fi - for file in ${files[*]}; do - echo "Copy and import file $file" - cp -p $file $CSMDATA/$dir - if [ $? -ne 0 ]; then - echo "Problem copying file: $file" - exit 3 - fi - chmod 0444 $CSMDATA/$dir/$file - if [ $? -ne 0 ]; then - echo "Problem chmod on file: $file" - exit 4 - fi - svn import $CSMDATA/$dir/$file $SVN_INP_DIR/$dir/$file -m "Mapping file for $res" - if [ $? -ne 0 ]; then - echo "Problem doing svn import on file: $file" - exit 4 - fi - done - fi -done diff --git a/tools/mkmapdata/regridbatch.sh b/tools/mkmapdata/regridbatch.sh deleted file mode 100755 index 8b56f2dc7d..0000000000 --- a/tools/mkmapdata/regridbatch.sh +++ /dev/null @@ -1,102 +0,0 @@ -#!/bin/bash -# -# -# Batch script to submit to create mapping files for all standard -# resolutions. If you provide a single resolution via "$RES", only -# that resolution will be used. In that case: If it is a regional or -# single point resolution, you should set '#PBS -n' to 1, and be sure -# that '-t regional' is specified in cmdargs. -# -# cheyenne specific batch commands: -#PBS -A P93300606 -#PBS -N regrid -#PBS -q regular -#PBS -l select=4:ncpus=2:mpiprocs=2:mem=109GB -#PBS -l walltime=2:00:00 -#PBS -j oe -#PBS -me -#PBS -V -#PBS -S /bin/bash - -#---------------------------------------------------------------------- -# Set parameters -#---------------------------------------------------------------------- - -#---------------------------------------------------------------------- -# Begin main script -#---------------------------------------------------------------------- - -if [ -z "$RES" ]; then - echo "Run for all valid resolutions" - resols=`../../bld/queryDefaultNamelist.pl -res list -silent` - if [ ! -z "$GRIDFILE" ]; then - echo "When GRIDFILE set RES also needs to be set for a single resolution" - exit 1 - fi -else - resols="$RES" -fi -if [ -z "$GRIDFILE" ]; then - grid="" -else - if [[ ${#resols[@]} > 1 ]]; then - echo "When GRIDFILE is specificed only one resolution can also be given (# resolutions ${#resols[@]})" - echo "Resolutions input is: $resols" - exit 1 - fi - grid="-f $GRIDFILE" -fi - -if [ -z "$MKMAPDATA_OPTIONS" ]; then - echo "Run with standard options" - options=" " -else - options="$MKMAPDATA_OPTIONS" -fi -echo "Create mapping files for this list of resolutions: $resols" - -#---------------------------------------------------------------------- - -for res in $resols; do - echo "Create mapping files for: $res" -#---------------------------------------------------------------------- - cmdargs="-r $res $grid $options" - - # For single-point and regional resolutions, tell mkmapdata that - # output type is regional - if [[ `echo "$res" | grep -c "1x1_"` -gt 0 || `echo "$res" | grep -c "5x5_"` -gt 0 ]]; then - res_type="regional" - else - res_type="global" - fi - # Assume if you are providing a gridfile that the grid is regional - if [ $grid != "" ];then - res_type="regional" - fi - - cmdargs="$cmdargs -t $res_type" - - echo "$res_type" - if [ "$res_type" = "regional" ]; then - echo "regional" - # For regional and (especially) single-point grids, we can get - # errors when trying to use multiple processors - so just use 1. - regrid_num_proc=1 - else - echo "global" - regrid_num_proc=8 - fi - - if [ ! -z "$LSFUSER" ]; then - echo "batch" - cmdargs="$cmdargs -b" - fi - if [ ! -z "$PBS_O_WORKDIR" ]; then - cd $PBS_O_WORKDIR - cmdargs="$cmdargs -b" - fi - - echo "args: $cmdargs" - echo "time env REGRID_PROC=$regrid_num_proc ./mkmapdata.sh $cmdargs\n" - time env REGRID_PROC=$regrid_num_proc ./mkmapdata.sh $cmdargs -done diff --git a/tools/mkmapdata/regridgeyser.sh b/tools/mkmapdata/regridgeyser.sh deleted file mode 100755 index 82a4615dcd..0000000000 --- a/tools/mkmapdata/regridgeyser.sh +++ /dev/null @@ -1,87 +0,0 @@ -#!/bin/bash -# -# -# Batch script to submit to create mapping files for all standard -# resolutions. If you provide a single resolution via "$RES", only -# that resolution will be used. In that case: If it is a regional or -# single point resolution, you should set '#SBATCH -n' to 1, and be sure -# that '-t regional' is specified in cmdargs. -# -# geyser specific batch commands: -#SBATCH -J regrid # job name -#SBATCH -n 8 -#SBATCH --ntasks-per-node=8 -#SBATCH --mem=450G -#SBATCH -t 03:00:00 -#SBATCH -A P93300606 -#SBATCH -p dav -#SBATCH -e regrid.%J.out # output filename -#SBATCH -o regrid.%J.err # error filename -# -# To submit this script: -# -# sbatch regridgeyser.sh -# -## IMPORTANT NOTE: -# -# environment variables can NOT be passed into DAV -# queues. Hence, this script MUST be edited to select -# what resolution to run for. - -#---------------------------------------------------------------------- -# Set parameters -#---------------------------------------------------------------------- -export RES=1x1_brazil - -#---------------------------------------------------------------------- -# Begin main script -#---------------------------------------------------------------------- - -if [ -z "$RES" ]; then - echo "Run for all valid resolutions" - resols=`../../bld/queryDefaultNamelist.pl -res list -silent` -else - resols="$RES" -fi -echo "Create mapping files for this list of resolutions: $resols" - -#---------------------------------------------------------------------- - -for res in $resols; do - echo "Create mapping files for: $res" -#---------------------------------------------------------------------- - cmdargs="-r $res" - - # For single-point and regional resolutions, tell mkmapdata that - # output type is regional - if [[ `echo "$res" | grep -c "1x1_"` -gt 0 || `echo "$res" | grep -c "5x5_"` -gt 0 ]]; then - res_type="regional" - else - res_type="global" - fi - - cmdargs="$cmdargs -t $res_type" - - echo "$res_type" - if [ "$res_type" = "regional" ]; then - echo "regional" - # For regional and (especially) single-point grids, we can get - # errors when trying to use multiple processors - so just use 1. - # We also do NOT set batch mode in this case, because some - # machines (e.g., yellowstone) do not listen to REGRID_PROC, so to - # get a single processor, we need to run mkmapdata.sh in - # interactive mode. - regrid_num_proc=1 - else - echo "global" - regrid_num_proc=$SLURM_NTASKS - if [ ! -z "$SLURM_JOB_ACCOUNT" ]; then - echo "batch" - cmdargs="$cmdargs -b" - fi - fi - - echo "args: $cmdargs" - echo "time env REGRID_PROC=$regrid_num_proc ./mkmapdata.sh $cmdargs\n" - time env REGRID_PROC=$regrid_num_proc ./mkmapdata.sh $cmdargs -done diff --git a/tools/mkmapdata/rmdups.ncl b/tools/mkmapdata/rmdups.ncl deleted file mode 100644 index d5fff40d53..0000000000 --- a/tools/mkmapdata/rmdups.ncl +++ /dev/null @@ -1,131 +0,0 @@ -; -; Remove duplicate weights from a mapping file. -; -; Mark Taylor (converted for use by CLM mkmapdata by Erik Kluzek) -; Sep/01/2011 -; -load "$NCARG_NCARG/nclscripts/csm/gsn_code.ncl" -load "$NCARG_NCARG/nclscripts/csm/gsn_csm.ncl" -load "$NCARG_NCARG/nclscripts/csm/contributed.ncl" -begin - ; =========================================================================================================== - ; - ; IMPORTANT NOTE: EDIT THE FOLLOWING TO CUSTOMIZE or use ENV VARIABLE SETTINGS - ; Edit the following as needed - ; - ; Input mapping file to remove duplicate weights from a mapping file - ; - mapfile = getenv("MAPFILE") ; Get the mapping file - newmapfile = getenv("NEWMAPFILE") ; The new mapping file to create - logname = getenv("LOGNAME") ; Logname of user running the script - - if ( ismissing(mapfile) )then - print( "You did NOT enter an input mapping file to convert" ) - status_exit( -1 ) - end if - if ( ismissing(newmapfile) )then - sdate = systemfunc( "date +%y%m%d" ); - newmapfile = mapfile+"_c"+sdate+".nc"; - end if - ; =========================================================================================================== - - if ( systemfunc("test -f "+mapfile+"; echo $?" ) .ne. 0 )then - print( "Input file does not exist or not found: "+mapfile ); - status_exit( -1 ) - end if - print("map file: "+mapfile) - f = addfile(mapfile,"r") ; Open netCDF files. - - - n_s = dimsizes(f->col) - if ( n_s .eq. 0 )then - print( "n_s is size zero, so no overlap points just return: " ); - exit - end if - - n_b = dimsizes(f->area_b) - n_a = dimsizes(f->area_a) - print("n_s = "+n_s+" max(row)="+max(f->row)+" max(col)="+max(f->col)) - - - - row = f->row - col = f->col - - - print("checking for dups, sorting...") - hash = new( n_s, double ) - hash = col - hash= hash + row*n_b - index1d=dim_pqsort(hash,1) - row2=row(index1d) - col2=col(index1d) - S=f->S - print("zeroing out any dups...") - ndups=0 - i0=0 - do i=1,n_s-1 - if ( (col2(i) .eq. col2(i0)) .and. (row2(i) .eq. row2(i0))) then - iorig1 = index1d(i0) - iorig2 = index1d(i) - ;print("dup row: "+row2(i)+" "+row2(i0)+" "+row(iorig1)+" "+row(iorig2)) - ;print("dup col: "+col2(i)+" "+col2(i0)+" "+col(iorig1)+" "+col(iorig2)) - ;print("removing "+iorig2+" keeping "+iorig1) - S(iorig1)=S(iorig1)+S(iorig2) - S(iorig2)=0 - ndups=ndups+1 - ; dont increment i0 - else - i0=i - end if - end do - delete(row2) - delete(col2) - if ( ndups .gt. 0) then - print("ndups = "+ndups) - print("compacting S...") - ns2 = n_s-ndups - S2 = new( ns2, double) - row2= new( ns2, integer) - col2 = new( ns2, integer) - ns2=0 - do i=0,n_s-1 - if (S(i) .ne. 0) then - S2(ns2)=S(i) - row2(ns2)=row(i) - col2(ns2)=col(i) - ns2=ns2+1 - end if - end do - print("removed "+ndups+" dups") - delete(S) - delete(row) - delete(col) - S=S2 - row=row2 - col=col2 - n_s = ns2 - print("writing new netcdf file") - cmdout = systemfunc("ncks -O -x -v S,row,col "+mapfile+" "+newmapfile) - nco = addfile(newmapfile,"rw") ; Open netCDF files. - nco->S = S - nco->row = row - nco->col = col - ldate = systemfunc( "date" ); - nco@history = nco@history + ":"+ldate + ": "; - nco@history = nco@history + " Removed duplicate weights from mapping file with: rmdups.ncl " - nco@rmdups_Logname = logname; - nco@rmdups_mod_date = ldate; - nco@rmdups_version = systemfunc( "git describe" ); - - print("Successfully removed duplicate weights from mapping file" ); - - else - - print("No duplicate weights to remove from mapping file" ); - - end if - - - -end diff --git a/tools/mkprocdata_map/README b/tools/mkprocdata_map/README index f5ac71b1ff..92ffb4856c 100644 --- a/tools/mkprocdata_map/README +++ b/tools/mkprocdata_map/README @@ -47,8 +47,7 @@ the output. However, you may want to wrap this in a job script to run it on multiple processors (using mpirun), and you may have to set other - machine-specific environment variables. You can follow the method - used in tools/mkmapdata/mkmapdata.sh. + machine-specific environment variables. (4) Build the mkprocdata_map tool. From the current directory, do the following: diff --git a/tools/mkprocdata_map/src/Makefile b/tools/mkprocdata_map/src/Makefile index 6f07deb741..42f797b3c2 100644 --- a/tools/mkprocdata_map/src/Makefile +++ b/tools/mkprocdata_map/src/Makefile @@ -1,4 +1,4 @@ -# Makefile for mksurfdata_map +# Makefile for mkprocdata_map EXENAME = ../mkprocdata_map @@ -7,4 +7,4 @@ ifeq ($(OPT),$(null)) OPT := TRUE endif -include Makefile.common \ No newline at end of file +include Makefile.common diff --git a/tools/mksurfdata_esmf/Makefile b/tools/mksurfdata_esmf/Makefile new file mode 100644 index 0000000000..fc81d48079 --- /dev/null +++ b/tools/mksurfdata_esmf/Makefile @@ -0,0 +1,390 @@ +# -*- mode:Makefile -*- +# +# Before running "make urban-alpha" or any target that includes it, +# execute "module load nco" first. +# +# To generate all surface data sets, run: +# make all +# +# To generate all surface data sets that use subset_data to be generated: +# make all-subset +# +# To generate a single dataset, run make with the name of the rule you +# want to build. For example, to generate the crop data set for 1x1_numaIA: +# +# make crop-numa +# +# NOTE: The default behavior is to parallelize data set creation using +# the batch system by submitting jobs to the batch queue (on Derecho). +# +# In all cases where "--scenario $@" appears, the code executes the +# recipe for the specific target/scenario that it finds in +# ../../python/ctsm/toolchain/gen_mksurfdata_jobscript_multi.py +# There are a few grids mentioned explicitly here in the Makefile and +# many others that only appear in the gen_mksurfdata_jobscript_multi.py +# Look for resolutions or groups of resolutions in that python code. +# + +# Set up special characters +null := + +# Set a few things needed for batch handling +PROJECT = $(shell cat $(HOME)/.cesm_proj) +LOGOUT = $@.stdout.txt +PWD = $(shell pwd) + +BATCHJOBS_ch = qsub +ifeq ($(PROJECT),$(null)) + $(error Can NOT find PROJECT number from ~/.cesm_proj file create it and try again) +endif +BATCHJOBS = $(BATCHJOBS_ch) + +MKSURFDATA = $(PWD)/gen_mksurfdata_jobscript_multi --account $(PROJECT) +SUBSETDATA = $(PWD)/../site_and_regional/subset_data +MODIFYSURF = $(PWD)/../modify_input_files/fsurdat_modifier --overwrite + +CDATE = $(shell date +%y%m%d) + +# subset_data options +# +SUBSETDATA_POINT = $(SUBSETDATA) point --silent --overwrite --uniform-snowpack --cap-saturation --crop --outdir . +SUBSETDATA_POINT_ALLLU = $(SUBSETDATA_POINT) --include-nonveg +SUBSETDATA_POINT_URBAN = $(SUBSETDATA_POINT) --include-nonveg + +# Subset data sites... +SUBSETDATA_1X1_BRAZIL := --lat -7 --lon -55 --site 1x1_brazil +SUBSETDATA_1X1_NUMAIA := --lat 40.6878 --lon 267.0228 --site 1x1_numaIA +SUBSETDATA_1X1_SMALL := --lat 40.6878 --lon 267.0228 --site 1x1_smallvilleIA \ + --dompft 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 \ + --pctpft 6.5 1.5 1.6 1.7 1.8 1.9 1.5 1.6 1.7 1.8 1.9 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 +# NOTE: The 1850 smallvilleIA site is constructed to start with 100% natural vegetation, so we can test transition to crops +SUBSETDATA_1X1_SMALL1850 := --lat 40.6878 --lon 267.0228 --site 1x1_smallvilleIA --dompft 13 --pctpft 100 +SUBSETDATA_1X1_SMALLTRANSIENT := --lat 40.6878 --lon 267.0228 --site 1x1_smallvilleIA + +MEXICOCITY_TMP_FNAME := surfdata_1x1_mexicocityMEX_hist_2000_78pfts.nc +MEXICOCITY_FNAME := surfdata_1x1_mexicocityMEX_hist_2000_78pfts_c$(CDATE).nc +VANCOUVER_TMP_FNAME := surfdata_1x1_vancouverCAN_hist_2000_78pfts.nc +VANCOUVER_FNAME := surfdata_1x1_vancouverCAN_hist_2000_78pfts_c$(CDATE).nc +URBALPHA_TMP_FNAME := surfdata_1x1_urbanc_alpha_hist_2000_78pfts.nc +URBALPHA_TMP2_FNAME := surfdata_1x1_urbanc_alpha_hist_2000_78pfts_tmp.nc +URBALPHA_FNAME := surfdata_1x1_urbanc_alpha_hist_2000_78pfts_c$(CDATE).nc +SUBSETDATA_1X1_MEXICOCITY := --lat 19.5 --lon 260.5 --site 1x1_mexicocityMEX --out-surface $(MEXICOCITY_TMP_FNAME) +SUBSETDATA_1X1_VANCOUVER := --lat 49.5 --lon 236.5 --site 1x1_vancouverCAN --out-surface $(VANCOUVER_TMP_FNAME) +SUBSETDATA_1X1_URBALPHA := --lat -37.7308 --lon 0 --site 1x1_urbanc_alpha --out-surface $(URBALPHA_TMP_FNAME) + +# ne120np4 and hi-res are for high resolution, ne16np4 is for mid-resolution testing +# low-res is for low resolutions for testing +# nldas is for NWP working with WRF +# STANDARD means no crop, so 16 pfts +STANDARD = \ + global-potveg \ + global-present \ + global-present-low-res \ + +CROP = \ + crop-global-present \ + crop-global-present-low-res \ + crop-global-present-ne16 \ + crop-global-present-ne30 \ + crop-global-present-ne120 \ + crop-global-present-mpasa480 \ + crop-global-present-nldas \ + crop-global-1850 \ + crop-global-1850-low-res \ + crop-global-1850-ne16 \ + crop-global-1850-ne30 \ + crop-global-1850-ne120 \ + crop-global-1850-mpasa480 \ + crop-global-future \ + +# Start all with all-subset because user is bound to forget to first run +# module load nco +# Usually, include global-present-ultra-hi-res temporarily while +# generating datasets for a new release +all : all-subset standard crop crop-tropics-present + +# These are all the surface datasets generated by subset_data +# This runs interactively and does not send jobs to the batch queue +all-subset : \ + 1x1_brazil-present \ + 1x1_brazil-transient \ + 1x1-numa-present \ + 1x1-smallville-present \ + 1x1-smallville-1850 \ + 1x1-smallville-transient \ + urban + +DEBUG: + @echo "HOST := $(HOST)" + @echo "PROJECT := $(PROJECT)" + @echo "MKSURFDATA := $(MKSURFDATA)" + @echo "SUBSETDATA_POINT := $(SUBSETDATA_POINT)" + @echo "MODIFYSURF := $(MODIFYSURF)" + @echo "BATCHJOBS := $(BATCHJOBS)" + @echo "CDATE := $(CDATE)" + @echo "RM := $(RM)" + +# +# standard +# +standard : $(STANDARD) + +global-potveg : FORCE + $(MKSURFDATA) --number-of-nodes 4 --scenario $@ --jobscript-file $@.sh --walltime 01:00:00 + $(BATCHJOBS) $@.sh + +global-present : FORCE + $(MKSURFDATA) --number-of-nodes 4 --scenario $@ --jobscript-file $@.sh --walltime 01:00:00 + $(BATCHJOBS) $@.sh + +global-present-low-res : FORCE + $(MKSURFDATA) --number-of-nodes 1 --tasks-per-node 64 --scenario $@ --jobscript-file $@.sh --walltime 01:00:00 + $(BATCHJOBS) $@.sh + +# +# Ultra high resolutions (Don't do by default user should select this by hand) +# +global-present-ultra-hi-res : FORCE + $(MKSURFDATA) --number-of-nodes 50 --scenario $@ --jobscript-file $@.sh --walltime 01:00:00 + $(BATCHJOBS) $@.sh + +# +# tropics +# + +crop-tropics-present : FORCE + $(MKSURFDATA) --number-of-nodes 1 --tasks-per-node 5 --scenario $@ --jobscript-file $@.sh --walltime 01:00:00 + $(BATCHJOBS) $@.sh + +1x1_brazil-present : FORCE + $(SUBSETDATA_POINT_ALLLU) --create-surface $(SUBSETDATA_1X1_BRAZIL) + +1x1_brazil-transient : FORCE + $(SUBSETDATA_POINT_ALLLU) --create-surface --create-landuse $(SUBSETDATA_1X1_BRAZIL) --cfg-file ../site_and_regional/default_data_1850.cfg + +# +# crop +# +crop : $(CROP) + +crop-global-present : FORCE + $(MKSURFDATA) --number-of-nodes 4 --scenario $@ --jobscript-file $@.sh --walltime 01:00:00 + $(BATCHJOBS) $@.sh + +crop-global-present-low-res : FORCE + $(MKSURFDATA) --number-of-nodes 1 --tasks-per-node 64 --scenario $@ --jobscript-file $@.sh --walltime 12:00:00 + $(BATCHJOBS) $@.sh + +crop-global-present-ne16 : FORCE + $(MKSURFDATA) --number-of-nodes 4 --scenario $@ --jobscript-file $@.sh --walltime 01:00:00 + $(BATCHJOBS) $@.sh + +crop-global-present-ne30 : FORCE + $(MKSURFDATA) --number-of-nodes 4 --scenario $@ --jobscript-file $@.sh --walltime 01:00:00 + $(BATCHJOBS) $@.sh + +crop-global-present-ne120 : FORCE + $(MKSURFDATA) --number-of-nodes 4 --scenario $@ --jobscript-file $@.sh --walltime 01:00:00 + $(BATCHJOBS) $@.sh + +crop-global-present-mpasa480 : FORCE + $(MKSURFDATA) --number-of-nodes 4 --scenario $@ --jobscript-file $@.sh --walltime 01:00:00 + $(BATCHJOBS) $@.sh + +crop-global-present-nldas : FORCE + $(MKSURFDATA) --number-of-nodes 4 --scenario $@ --jobscript-file $@.sh --walltime 01:00:00 + $(BATCHJOBS) $@.sh + +crop-global-1850 : FORCE + $(MKSURFDATA) --number-of-nodes 4 --scenario $@ --jobscript-file $@.sh --walltime 01:00:00 + $(BATCHJOBS) $@.sh + +crop-global-1850-low-res : FORCE + $(MKSURFDATA) --number-of-nodes 1 --tasks-per-node 64 --scenario $@ --jobscript-file $@.sh --walltime 12:00:00 + $(BATCHJOBS) $@.sh + +crop-global-1850-ne16 : FORCE + $(MKSURFDATA) --number-of-nodes 4 --scenario $@ --jobscript-file $@.sh --walltime 01:00:00 + $(BATCHJOBS) $@.sh + +crop-global-1850-ne30 : FORCE + $(MKSURFDATA) --number-of-nodes 4 --scenario $@ --jobscript-file $@.sh --walltime 01:00:00 + $(BATCHJOBS) $@.sh + +crop-global-1850-ne120 : FORCE + $(MKSURFDATA) --number-of-nodes 4 --scenario $@ --jobscript-file $@.sh --walltime 01:00:00 + $(BATCHJOBS) $@.sh + +crop-global-1850-mpasa480 : FORCE + $(MKSURFDATA) --number-of-nodes 4 --scenario $@ --jobscript-file $@.sh --walltime 01:00:00 + $(BATCHJOBS) $@.sh + +crop-global-hist : FORCE + $(MKSURFDATA) --number-of-nodes 72 --scenario $@ --jobscript-file $@.sh --walltime 12:00:00 + $(BATCHJOBS) $@.sh + +crop-global-hist-low-res : FORCE + $(MKSURFDATA) --number-of-nodes 14 --tasks-per-node 32 --scenario $@ --jobscript-file $@.sh --walltime 12:00:00 + $(BATCHJOBS) $@.sh + +crop-global-hist-ne16 : FORCE + $(MKSURFDATA) --number-of-nodes 9 --scenario $@ --jobscript-file $@.sh --walltime 12:00:00 + $(BATCHJOBS) $@.sh + +crop-global-hist-ne30 : FORCE + $(MKSURFDATA) --number-of-nodes 9 --scenario $@ --jobscript-file $@.sh --walltime 12:00:00 + $(BATCHJOBS) $@.sh + +1x1-numa-present : FORCE + $(SUBSETDATA_POINT_ALLLU) --create-surface $(SUBSETDATA_1X1_NUMAIA) + +1x1-smallville-present : FORCE + $(SUBSETDATA_POINT) --create-surface $(SUBSETDATA_1X1_SMALL) + +# Note that the smallville 1850 dataset is entirely natural vegetation. This +# facilitates testing a transient case that starts with no crop, and then later +# adds crop (to make sure that it works properly to add crop in a grid cell +# where there used to be no crop). +1x1-smallville-1850 : FORCE + $(SUBSETDATA_POINT) --create-surface $(SUBSETDATA_1X1_SMALL1850) --cfg-file ../site_and_regional/default_data_1850.cfg + +# Note (slevis): The next line makes the landuse.timeseries from 1850 to 2015, so also run +# modify_smallville.sh to generate three modified landuse.timeseries files needed for testing. +1x1-smallville-transient : FORCE + $(SUBSETDATA_POINT) --create-landuse $(SUBSETDATA_1X1_SMALLTRANSIENT) + ../modify_input_files/modify_smallville.sh + +# +# Crop with future scenarios +# + +crop-global-future : crop-global-SSP1-1.9-f09 \ + crop-global-SSP1-2.6-f09 \ + crop-global-SSP2-4.5 \ + crop-global-SSP2-4.5-low-res \ + crop-global-SSP3-7.0-f09 \ + crop-global-SSP4-3.4-f09 \ + crop-global-SSP4-6.0-f09 \ + crop-global-SSP5-8.5-f09 + +crop-global-SSP2-4.5-low-res : crop-global-SSP2-4.5-f10 \ + crop-global-SSP2-4.5-f45 \ + crop-global-SSP2-4.5-ne3 +crop-global-SSP2-4.5 : crop-global-SSP2-4.5-f09 \ + crop-global-SSP2-4.5-f19 \ + crop-global-SSP2-4.5-hcru \ + crop-global-SSP2-4.5-ne16 \ + crop-global-SSP2-4.5-ne30 \ + crop-global-SSP2-4.5-C96 \ + crop-global-SSP2-4.5-mpasa120 + +crop-global-SSP1-1.9-f09 : FORCE + $(MKSURFDATA) --number-of-nodes 9 --scenario $@ --jobscript-file $@.sh --walltime 12:00:00 + $(BATCHJOBS) $@.sh + +crop-global-SSP1-2.6-f09 : FORCE + $(MKSURFDATA) --number-of-nodes 9 --scenario $@ --jobscript-file $@.sh --walltime 12:00:00 + $(BATCHJOBS) $@.sh + +crop-global-SSP2-4.5-f09 : FORCE + $(MKSURFDATA) --number-of-nodes 9 --scenario $@ --jobscript-file $@.sh --walltime 12:00:00 + $(BATCHJOBS) $@.sh + +crop-global-SSP2-4.5-f19 : FORCE + $(MKSURFDATA) --number-of-nodes 8 --scenario $@ --jobscript-file $@.sh --walltime 12:00:00 + $(BATCHJOBS) $@.sh + +crop-global-SSP2-4.5-f10 : FORCE + $(MKSURFDATA) --number-of-nodes 8 --tasks-per-node 16 --scenario $@ --jobscript-file $@.sh --walltime 12:00:00 + $(BATCHJOBS) $@.sh + +crop-global-SSP2-4.5-f45 : FORCE + $(MKSURFDATA) --number-of-nodes 14 --tasks-per-node 32 --scenario $@ --jobscript-file $@.sh --walltime 12:00:00 + $(BATCHJOBS) $@.sh + +crop-global-SSP2-4.5-hcru : FORCE + $(MKSURFDATA) --number-of-nodes 72 --scenario $@ --jobscript-file $@.sh --walltime 12:00:00 + $(BATCHJOBS) $@.sh + +crop-global-SSP2-4.5-ne3 : FORCE + $(MKSURFDATA) --number-of-nodes 14 --tasks-per-node 32 --scenario $@ --jobscript-file $@.sh --walltime 12:00:00 + $(BATCHJOBS) $@.sh + +crop-global-SSP2-4.5-ne16 : FORCE + $(MKSURFDATA) --number-of-nodes 8 --scenario $@ --jobscript-file $@.sh --walltime 12:00:00 + $(BATCHJOBS) $@.sh + +crop-global-SSP2-4.5-ne30 : FORCE + $(MKSURFDATA) --number-of-nodes 9 --scenario $@ --jobscript-file $@.sh --walltime 12:00:00 + $(BATCHJOBS) $@.sh + +crop-global-SSP2-4.5-C96 : FORCE + $(MKSURFDATA) --number-of-nodes 9 --scenario $@ --jobscript-file $@.sh --walltime 12:00:00 + $(BATCHJOBS) $@.sh + +crop-global-SSP2-4.5-mpasa120 : FORCE + $(MKSURFDATA) --number-of-nodes 9 --scenario $@ --jobscript-file $@.sh --walltime 12:00:00 + $(BATCHJOBS) $@.sh + +# Don't do the high-resolution cases by default... +crop-global-SSP2-4.5-hi-res : FORCE + $(MKSURFDATA) --number-of-nodes 6 --scenario $@ --jobscript-file $@.sh --walltime 12:00:00 + $(BATCHJOBS) $@.sh + +crop-global-SSP3-7.0-f09 : FORCE + $(MKSURFDATA) --number-of-nodes 9 --scenario $@ --jobscript-file $@.sh --walltime 12:00:00 + $(BATCHJOBS) $@.sh + +crop-global-SSP4-3.4-f09 : FORCE + $(MKSURFDATA) --number-of-nodes 9 --scenario $@ --jobscript-file $@.sh --walltime 12:00:00 + $(BATCHJOBS) $@.sh + +crop-global-SSP4-6.0-f09 : FORCE + $(MKSURFDATA) --number-of-nodes 9 --scenario $@ --jobscript-file $@.sh --walltime 12:00:00 + $(BATCHJOBS) $@.sh + +crop-global-SSP5-8.5-f09 : FORCE + $(MKSURFDATA) --number-of-nodes 9 --scenario $@ --jobscript-file $@.sh --walltime 12:00:00 + $(BATCHJOBS) $@.sh + +# +# urban +# +urban : urban-present urban-alpha + +urban-present : mexicocity vancouver + +mexicocity : FORCE + $(SUBSETDATA_POINT_URBAN) --create-surface $(SUBSETDATA_1X1_MEXICOCITY) + $(MODIFYSURF) modify_1x1_mexicocityMEX.cfg -i $(MEXICOCITY_TMP_FNAME) -o $(MEXICOCITY_FNAME) + $(RM) $(MEXICOCITY_TMP_FNAME) + +vancouver : FORCE + $(SUBSETDATA_POINT_URBAN) --create-surface $(SUBSETDATA_1X1_VANCOUVER) + $(MODIFYSURF) modify_1x1_vancouverCAN.cfg -i $(VANCOUVER_TMP_FNAME) -o $(VANCOUVER_FNAME) + $(RM) $(VANCOUVER_TMP_FNAME) + +# NOTE(bja, 2015-01) skip abort on invalid data necessary as of 2015-01. See +# /glade/campaign/cesm/cesmdata/inputdata/lnd/clm2/surfdata_map/README_c141219 +urban-alpha : FORCE + $(SUBSETDATA_POINT_URBAN) --create-surface $(SUBSETDATA_1X1_URBALPHA) + # Set number of nlevurb dimension to 4 for this site + ncks -O --dmn nlevurb,0,3 -o $(URBALPHA_TMP2_FNAME) $(URBALPHA_TMP_FNAME) + $(MODIFYSURF) modify_1x1_urbanc_alpha.cfg -i $(URBALPHA_TMP2_FNAME) -o $(URBALPHA_FNAME) + $(RM) $(URBALPHA_TMP_FNAME) $(URBALPHA_TMP2_FNAME) + + +# +# clean up the working directory by removing generated files +# +clean : FORCE + -rm *~ + +clobber : clean + -rm surfdata_*.nc surfdata_*.log surfdata_*.namelist + +# +# generic rule to force things to happen +# +FORCE : + diff --git a/tools/mksurfdata_esmf/README.md b/tools/mksurfdata_esmf/README.md new file mode 100644 index 0000000000..11cb69c681 --- /dev/null +++ b/tools/mksurfdata_esmf/README.md @@ -0,0 +1,215 @@ +# Instructions for Using mksurfdata_esmf to Create Surface Datasets + +## Table of contents +1. [Purpose](#purpose) +1. [Building](#building) +1. [Running a Single Submission](#running-for-a-single-submission) +1. [Running for Multiple Datasets](#running-for-the-generation-of-multiple-datasets) +1. [Notes](#notes) + + +## Purpose + +This tool is intended to generate fsurdat files (surface datasets) for the +CTSM. It can generate global, regional, and single-point fsurdat files, as long +as a mesh file is available for the grid. + +The subset_data tool allows users to make fsurdat files from existing fsurdat +files when a mesh file is unavailable. Generally, users should consider the +subset_data tool for generating regional and single-point fsurdat files. + + +## Building + + + +### Build Requirements + + +mksurfdata_esmf is a distributed memory parallel program (using Message Passing +Interface -- MPI) that utilizes both ESMF (Earth System Modelling Framework) +for regridding as well as PIO (Parallel I/O) and NetCDF output. As +such, libraries must be built for the following: + +1. MPI +2. NetCDF +3. PIO +4. ESMF + +In addition for the build: python, bash-shell, CMake and GNU-Make are required + +These libraries need to be built such that they can all work together in the +same executable. Hence, the above order may be required in building them. + +CTSM externals that are required are: cime and ccs_config. See [Building](#building-the-executable) on getting +those. A python environment that includes particular packages is also required +we demonstrate how to use the ctsm_pylib environment that we support in CTSM. + +Note, PNETCDF is an optional library that can be used, but is NOT required. + +#### Use cime to manage the build requirements + +See [IMPORTANT NOTE](important note-only-working-on-derecho-currently) + +For users working on cime machines you can use the build script to build the +tool. On other machines you'll need to do a port to cime and tell how to build +for that machine. That's talked about in the cime documentation. +And you'll have to make some modifications to the build script. + +https://github.com/ESMCI/cime/wiki/Porting-Overview + +Machines that already run CTSM or CESM have been ported to cime. So if you can +run the model on your machine, you will be able to build the tool there. + +To get a list of the machines that have been ported to cime: + +``` shell +# Assuming pwd is the tools/mksurfdata_esmf directory +cd ../../cime/scripts # or ../../../../cime/scripts for a CESM checkout +./query_config --machines +``` + +#### NOTE: +In addition to having a port to cime, the machine also needs to have PIO built +and able to be referenced with the env variable PIO which will need to be in +the porting instructions for the machine. An independent PIO library +is available on supported CESM machines. + + +#### IMPORTANT NOTE: ONLY WORKING ON DERECHO CURRENTLY + + + +> [!IMPORTANT] +> Currently we have run and tested mksurfdata_esmf on Derecho. Please see this github issue about mksurfdata_esmf on other CESM machines: + +https://github.com/ESCOMP/CTSM/issues/2341 + + +### Building the executable + + + Before starting, be sure that you have run + +``` shell +# Assuming pwd is the tools/mksurfdata_esmf directory + ./manage_externals/checkout_externals # Assuming at the top level of the CTSM/CESM checkout +``` + +This will bring in CIME and ccs_config which are required for building. + +``` shell +# Assuming pwd is the tools/mksurfdata_esmf directory + ./gen_mksurfdata_build # For machines with a cime build +``` + + Note: The pio_iotype value gets set and written to a simple .txt file + by this build script. The value depends on your machine. If not running + on derecho, casper, or izumi, you may need to update this, though + a default value does get set for other machines. + + +## Running for a single submission + + +### Setup ctsm_pylib + Work in the ctsm_pylib environment, which requires the following steps when + running on Derecho. On other machines it will be similar but might be different + in order to get conda in your path and activate the ctsm_pylib environment. + +``` shell +# Assuming pwd is the tools/mksurfdata_esmf directory + module load conda + cd ../.. # or ../../../.. for a CESM checkout) + ./py_env_create # Assuming at the top level of the CTSM/CESM checkout + conda activate ctsm_pylib +``` + +to generate your target namelist: + +``` shell +# Assuming pwd is the tools/mksurfdata_esmf directory + ./gen_mksurfdata_namelist --help +``` + +for example try --res 1.9x2.5 --start-year 1850 --end-year 1850: + +``` shell +# Assuming pwd is the tools/mksurfdata_esmf directory + ./gen_mksurfdata_namelist --res --start-year --end-year +``` + +> [!TIP] +> **IF FILES ARE MISSING FROM** /inputdata, a target namelist will be generated +> but with a generic name and with warning to run `./download_input_data` next. +> **IF A SMALLER SET OF FILES IS STILL MISSING AFTER RUNNING** `./download_input_data` +> and rerunning `./gen_mksurfdata_namelist`, then rerun +> `./gen_mksurfdata_namelist with your options needed. +> and rerun `./download_input_data` until +> `./gen_mksurfdata_namelist` finds all files. + + Example, to generate your target jobscript (again use --help for instructions): + +``` shell +# Assuming pwd is the tools/mksurfdata_esmf directory + ./gen_mksurfdata_jobscript_single --number-of-nodes 2 --tasks-per-node 128 --namelist-file target.namelist + qsub mksurfdata_jobscript_single.sh +``` + + Read note about regional grids at the end. + + +## Running for the generation of multiple datasets + + Work in the ctsm_pylib environment, as explained in earlier section. + gen_mksurfdata_jobscript_multi runs `./gen_mksurfdata_namelist` for you + +``` shell +# Assuming pwd is the tools/mksurfdata_esmf directory + ./gen_mksurfdata_jobscript_multi --number-of-nodes 2 --scenario global-present + qsub mksurfdata_jobscript_multi.sh +``` + + If you are looking to generate all (or a large number of) the datasets or the + single-point (1x1) datasets, you are best off using the Makefile. For example + +``` shell +# Assuming pwd is the tools/mksurfdata_esmf directory + make all # ...or + make all-subset +``` + + +## NOTES + + +# Guidelines for input datasets to mksurfdata_esmf + +> [!TIP] +> ALL raw datasets \*.nc **FILES MUST NOT BE NetCDF4**. + +Example to convert to CDF5 + +``` shell +nccopy -k cdf5 oldfile newfile +``` + +> [!TIP] +> The LAI raw dataset \*.nc **FILE MUST HAVE** an "unlimited" time dimension + +Example to change time to unlimted dimension using the NCO operator ncks. + +``` shell +ncks --mk_rec_dmn time file_with_time_equals_12.nc -o file_with_time_unlimited.nc +``` + +### IMPORTANT THERE HAVE BEEN PROBLEMS with REGIONAL grids!! + +> [!CAUTION] +> See +> +> https://github.com/ESCOMP/CTSM/issues/2430 + +In general we recommend using subset_data and/or fsurdat_modifier +for regional grids. + diff --git a/tools/mksurfdata_esmf/cmake/FindESMF.cmake b/tools/mksurfdata_esmf/cmake/FindESMF.cmake new file mode 100644 index 0000000000..e67e45c489 --- /dev/null +++ b/tools/mksurfdata_esmf/cmake/FindESMF.cmake @@ -0,0 +1,130 @@ +# - Try to find ESMF +# +# Requires setting ESMFMKFILE to the filepath of esmf.mk. If this is NOT set, +# then ESMF_FOUND will always be FALSE. If ESMFMKFILE exists, then ESMF_FOUND=TRUE +# and all ESMF makefile variables will be set in the global scope. Optionally, +# set ESMF_MKGLOBALS to a string list to filter makefile variables. For example, +# to globally scope only ESMF_LIBSDIR and ESMF_APPSDIR variables, use this CMake +# command in CMakeLists.txt: +# +# set(ESMF_MKGLOBALS "LIBSDIR" "APPSDIR") + + +# Add the ESMFMKFILE path to the cache if defined as system env variable +if (DEFINED ENV{ESMFMKFILE} AND NOT DEFINED ESMFMKFILE) + set(ESMFMKFILE $ENV{ESMFMKFILE} CACHE FILEPATH "Path to ESMF mk file") +endif () + +# Found the mk file and ESMF exists on the system +if (EXISTS ${ESMFMKFILE}) + set(ESMF_FOUND TRUE CACHE BOOL "ESMF mk file found" FORCE) + # Did not find the ESMF mk file +else() + set(ESMF_FOUND FALSE CACHE BOOL "ESMF mk file NOT found" FORCE) + # Best to warn users that without the mk file there is no way to find ESMF + if (NOT DEFINED ESMFMKFILE) + message(FATAL_ERROR "ESMFMKFILE not defined. This is the path to esmf.mk file. \ +Without this filepath, ESMF_FOUND will always be FALSE.") + endif () +endif() + +# Only parse the mk file if it is found +if (ESMF_FOUND) + # Read the mk file + file(STRINGS "${ESMFMKFILE}" esmfmkfile_contents) + # Parse each line in the mk file + foreach(str ${esmfmkfile_contents}) + # Only consider uncommented lines + string(REGEX MATCH "^[^#]" def ${str}) + # Line is not commented + if (def) + # Extract the variable name + string(REGEX MATCH "^[^=]+" esmf_varname ${str}) + # Extract the variable's value + string(REGEX MATCH "=.+$" esmf_vardef ${str}) + # Only for variables with a defined value + if (esmf_vardef) + # Get rid of the assignment string + string(SUBSTRING ${esmf_vardef} 1 -1 esmf_vardef) + # Remove whitespace + string(STRIP ${esmf_vardef} esmf_vardef) + # A string or single-valued list + if(NOT DEFINED ESMF_MKGLOBALS) + # Set in global scope + set(${esmf_varname} ${esmf_vardef}) + # Don't display by default in GUI + mark_as_advanced(esmf_varname) + else() # Need to filter global promotion + foreach(m ${ESMF_MKGLOBALS}) + string(FIND ${esmf_varname} ${m} match) + # Found the string + if(NOT ${match} EQUAL -1) + # Promote to global scope + set(${esmf_varname} ${esmf_vardef}) + # Don't display by default in the GUI + mark_as_advanced (esmf_varname) + # No need to search for the current string filter + break() + endif() + endforeach() + endif() + endif() + endif() + endforeach() + + # Construct ESMF_VERSION from ESMF_VERSION_STRING_GIT + if(ESMF_FOUND) + # ESMF_VERSION_MAJOR and ESMF_VERSION_MINOR are defined in ESMFMKFILE + set(ESMF_VERSION 0) + set(ESMF_VERSION_PATCH ${ESMF_VERSION_REVISION}) + set(ESMF_BETA_RELEASE FALSE) + if(ESMF_VERSION_BETASNAPSHOT MATCHES "^('T')$") + set(ESMF_BETA_RELEASE TRUE) + string(REGEX REPLACE ".*beta_snapshot_*\([0-9]*\).*" "\\1" ESMF_BETA_SNAPSHOT "${ESMF_VERSION_STRING_GIT}") + endif() + set(ESMF_VERSION "${ESMF_VERSION_MAJOR}.${ESMF_VERSION_MINOR}.${ESMF_VERSION_PATCH}") + endif() + + separate_arguments(ESMF_F90COMPILEPATHS NATIVE_COMMAND ${ESMF_F90COMPILEPATHS}) + foreach (ITEM ${ESMF_F90COMPILEPATHS}) + string(REGEX REPLACE "^-I" "" ITEM "${ITEM}") + list(APPEND tmp ${ITEM}) + endforeach() + set(ESMF_F90COMPILEPATHS ${tmp}) + + add_library(esmf UNKNOWN IMPORTED) + # Look for static library, if not found try dynamic library + find_library(esmf_lib NAMES libesmf.a PATHS ${ESMF_LIBSDIR}) + if(esmf_lib MATCHES "esmf_lib-NOTFOUND") + message(STATUS "Static ESMF library not found, searching for dynamic library instead") + find_library(esmf_lib NAMES esmf_fullylinked PATHS ${ESMF_LIBSDIR}) + if(esmf_lib MATCHES "esmf_lib-NOTFOUND") + message(FATAL_ERROR "Neither the dynamic nor the static ESMF library was found") + endif() + set(ESMF_INTERFACE_LINK_LIBRARIES "") + else() + # When linking the static library, also need the ESMF linker flags; strip any leading/trailing whitespaces + string(STRIP "${ESMF_F90ESMFLINKRPATHS} ${ESMF_F90ESMFLINKPATHS} ${ESMF_F90LINKPATHS} ${ESMF_F90LINKLIBS} ${ESMF_F90LINKOPTS}" ESMF_INTERFACE_LINK_LIBRARIES) + endif() + + message(STATUS "Found ESMF library: ${esmf_lib}") + if(ESMF_BETA_RELEASE) + message(STATUS "Detected ESMF Beta snapshot ${ESMF_BETA_SNAPSHOT}") + endif() + + set_target_properties(esmf PROPERTIES + IMPORTED_LOCATION ${esmf_lib} + INTERFACE_INCLUDE_DIRECTORIES "${ESMF_F90COMPILEPATHS}" + INTERFACE_LINK_LIBRARIES "${ESMF_INTERFACE_LINK_LIBRARIES}") + +endif() + +## Finalize find_package +include(FindPackageHandleStandardArgs) + +find_package_handle_standard_args( ${CMAKE_FIND_PACKAGE_NAME} + REQUIRED_VARS ESMF_LIBSDIR + ESMF_INTERFACE_LINK_LIBRARIES + ESMF_F90COMPILEPATHS + VERSION_VAR ESMF_VERSION + HANDLE_COMPONENTS ) \ No newline at end of file diff --git a/tools/mksurfdata_esmf/cmake/FindNetCDF.cmake b/tools/mksurfdata_esmf/cmake/FindNetCDF.cmake new file mode 100644 index 0000000000..e335b95bd5 --- /dev/null +++ b/tools/mksurfdata_esmf/cmake/FindNetCDF.cmake @@ -0,0 +1,347 @@ +# (C) Copyright 2011- ECMWF. +# +# This software is licensed under the terms of the Apache Licence Version 2.0 +# which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. +# In applying this licence, ECMWF does not waive the privileges and immunities +# granted to it by virtue of its status as an intergovernmental organisation nor +# does it submit to any jurisdiction. + +# Try to find NetCDF includes and library. +# Supports static and shared libaries and allows each component to be found in sepearte prefixes. +# +# This module defines +# +# - NetCDF_FOUND - System has NetCDF +# - NetCDF_INCLUDE_DIRS - the NetCDF include directories +# - NetCDF_VERSION - the version of NetCDF +# - NetCDF_CONFIG_EXECUTABLE - the netcdf-config executable if found +# - NetCDF_PARALLEL - Boolean True if NetCDF4 has parallel IO support via hdf5 and/or pnetcdf +# - NetCDF_HAS_PNETCDF - Boolean True if NetCDF4 has pnetcdf support +# +# Deprecated Defines +# - NetCDF_LIBRARIES - [Deprecated] Use NetCDF::NetCDF_ targets instead. +# +# +# Following components are available: +# +# - C - C interface to NetCDF (netcdf) +# - CXX - CXX4 interface to NetCDF (netcdf_c++4) +# - Fortran - Fortran interface to NetCDF (netcdff) +# +# For each component the following are defined: +# +# - NetCDF__FOUND - whether the component is found +# - NetCDF__LIBRARIES - the libraries for the component +# - NetCDF__LIBRARY_SHARED - Boolean is true if libraries for component are shared +# - NetCDF__INCLUDE_DIRS - the include directories for specified component +# - NetCDF::NetCDF_ - target of component to be used with target_link_libraries() +# +# The following paths will be searched in order if set in CMake (first priority) or environment (second priority) +# +# - NetCDF_ROOT - root of NetCDF installation +# - NetCDF_PATH - root of NetCDF installation +# +# The search process begins with locating NetCDF Include headers. If these are in a non-standard location, +# set one of the following CMake or environment variables to point to the location: +# +# - NetCDF_INCLUDE_DIR or NetCDF_${comp}_INCLUDE_DIR +# - NetCDF_INCLUDE_DIRS or NetCDF_${comp}_INCLUDE_DIR +# +# Notes: +# +# - Use "NetCDF::NetCDF_" targets only. NetCDF_LIBRARIES exists for backwards compatibility and should not be used. +# - These targets have all the knowledge of include directories and library search directories, and a single +# call to target_link_libraries will provide all these transitive properties to your target. Normally all that is +# needed to build and link against NetCDF is, e.g.: +# target_link_libraries(my_c_tgt PUBLIC NetCDF::NetCDF_C) +# - "NetCDF" is always the preferred naming for this package, its targets, variables, and environment variables +# - For compatibility, some variables are also set/checked using alternate names NetCDF4, NETCDF, or NETCDF4 +# - Environments relying on these older environment variable names should move to using a "NetCDF_ROOT" environment variable +# - Preferred component capitalization follows the CMake LANGUAGES variables: i.e., C, Fortran, CXX +# - For compatibility, alternate capitalizations are supported but should not be used. +# - If no components are defined, all components will be searched +# + +list( APPEND _possible_components C CXX Fortran ) + +## Include names for each component +set( NetCDF_C_INCLUDE_NAME netcdf.h ) +set( NetCDF_CXX_INCLUDE_NAME netcdf ) +set( NetCDF_Fortran_INCLUDE_NAME netcdf.mod ) + +## Library names for each component +set( NetCDF_C_LIBRARY_NAME netcdf ) +set( NetCDF_CXX_LIBRARY_NAME netcdf_c++4 ) +set( NetCDF_Fortran_LIBRARY_NAME netcdff ) + +## Enumerate search components +foreach( _comp ${_possible_components} ) + string( TOUPPER "${_comp}" _COMP ) + set( _arg_${_COMP} ${_comp} ) + set( _name_${_COMP} ${_comp} ) +endforeach() + +set( _search_components C) +foreach( _comp ${${CMAKE_FIND_PACKAGE_NAME}_FIND_COMPONENTS} ) + string( TOUPPER "${_comp}" _COMP ) + set( _arg_${_COMP} ${_comp} ) + list( APPEND _search_components ${_name_${_COMP}} ) + if( NOT _name_${_COMP} ) + message(SEND_ERROR "Find${CMAKE_FIND_PACKAGE_NAME}: COMPONENT ${_comp} is not a valid component. Valid components: ${_possible_components}" ) + endif() +endforeach() +list( REMOVE_DUPLICATES _search_components ) + +## Search hints for finding include directories and libraries +foreach( _comp IN ITEMS "_" "_C_" "_Fortran_" "_CXX_" ) + foreach( _name IN ITEMS NetCDF4 NetCDF NETCDF4 NETCDF ) + foreach( _var IN ITEMS ROOT PATH ) + list(APPEND _search_hints ${${_name}${_comp}${_var}} $ENV{${_name}${_comp}${_var}} ) + list(APPEND _include_search_hints + ${${_name}${_comp}INCLUDE_DIR} $ENV{${_name}${_comp}INCLUDE_DIR} + ${${_name}${_comp}INCLUDE_DIRS} $ENV{${_name}${_comp}INCLUDE_DIRS} ) + endforeach() + endforeach() +endforeach() +#Old-school HPC module env variable names +foreach( _name IN ITEMS NetCDF4 NetCDF NETCDF4 NETCDF ) + foreach( _comp IN ITEMS "_C" "_Fortran" "_CXX" ) + list(APPEND _search_hints ${${_name}} $ENV{${_name}}) + list(APPEND _search_hints ${${_name}${_comp}} $ENV{${_name}${_comp}}) + endforeach() +endforeach() + +## Find headers for each component +set(NetCDF_INCLUDE_DIRS) +set(_new_search_components) +foreach( _comp IN LISTS _search_components ) + if(NOT ${PROJECT_NAME}_NetCDF_${_comp}_FOUND) + list(APPEND _new_search_components ${_comp}) + endif() + find_file(NetCDF_${_comp}_INCLUDE_FILE + NAMES ${NetCDF_${_comp}_INCLUDE_NAME} + DOC "NetCDF ${_comp} include directory" + HINTS ${_include_search_hints} ${_search_hints} + PATH_SUFFIXES include include/netcdf + ) + mark_as_advanced(NetCDF_${_comp}_INCLUDE_FILE) + message(DEBUG "NetCDF_${_comp}_INCLUDE_FILE: ${NetCDF_${_comp}_INCLUDE_FILE}") + if( NetCDF_${_comp}_INCLUDE_FILE ) + get_filename_component(NetCDF_${_comp}_INCLUDE_FILE ${NetCDF_${_comp}_INCLUDE_FILE} ABSOLUTE) + get_filename_component(NetCDF_${_comp}_INCLUDE_DIR ${NetCDF_${_comp}_INCLUDE_FILE} DIRECTORY) + list(APPEND NetCDF_INCLUDE_DIRS ${NetCDF_${_comp}_INCLUDE_DIR}) + endif() +endforeach() +if(NetCDF_INCLUDE_DIRS) + list(REMOVE_DUPLICATES NetCDF_INCLUDE_DIRS) +endif() +set(NetCDF_INCLUDE_DIRS "${NetCDF_INCLUDE_DIRS}" CACHE STRING "NetCDF Include directory paths" FORCE) + +## Find n*-config executables for search components +foreach( _comp IN LISTS _search_components ) + if( _comp MATCHES "^(C)$" ) + set(_conf "c") + elseif( _comp MATCHES "^(Fortran)$" ) + set(_conf "f") + elseif( _comp MATCHES "^(CXX)$" ) + set(_conf "cxx4") + endif() + find_program( NetCDF_${_comp}_CONFIG_EXECUTABLE + NAMES n${_conf}-config + HINTS ${NetCDF_INCLUDE_DIRS} ${_include_search_hints} ${_search_hints} + PATH_SUFFIXES bin Bin ../bin ../../bin + DOC "NetCDF n${_conf}-config helper" ) + message(DEBUG "NetCDF_${_comp}_CONFIG_EXECUTABLE: ${NetCDF_${_comp}_CONFIG_EXECUTABLE}") +endforeach() + +set(_C_libs_flag --libs) +set(_Fortran_libs_flag --flibs) +set(_CXX_libs_flag --libs) +set(_C_includes_flag --includedir) +set(_Fortran_includes_flag --includedir) +set(_CXX_includes_flag --includedir) +function(netcdf_config exec flag output_var) + set(${output_var} False PARENT_SCOPE) + if( exec ) + execute_process( COMMAND ${exec} ${flag} RESULT_VARIABLE _ret OUTPUT_VARIABLE _val) + if( _ret EQUAL 0 ) + string( STRIP ${_val} _val ) + set( ${output_var} ${_val} PARENT_SCOPE ) + endif() + endif() +endfunction() + +## Detect additional package properties +netcdf_config(${NetCDF_C_CONFIG_EXECUTABLE} --has-parallel4 _val) +if( NOT _val MATCHES "^(yes|no)$" ) + netcdf_config(${NetCDF_C_CONFIG_EXECUTABLE} --has-parallel _val) +endif() +if( _val MATCHES "^(yes)$" ) + set(NetCDF_PARALLEL TRUE CACHE STRING "NetCDF has parallel IO capability via pnetcdf or hdf5." FORCE) +else() + set(NetCDF_PARALLEL FALSE CACHE STRING "NetCDF has no parallel IO capability." FORCE) +endif() + +if(NetCDF_PARALLEL) + find_package(MPI REQUIRED) +endif() + +## Find libraries for each component +set( NetCDF_LIBRARIES ) +foreach( _comp IN LISTS _search_components ) + string( TOUPPER "${_comp}" _COMP ) + + find_library( NetCDF_${_comp}_LIBRARY + NAMES ${NetCDF_${_comp}_LIBRARY_NAME} + DOC "NetCDF ${_comp} library" + HINTS ${NetCDF_${_comp}_INCLUDE_DIRS} ${_search_hints} + PATH_SUFFIXES lib64 lib ../lib64 ../lib ../../lib64 ../../lib ) + mark_as_advanced( NetCDF_${_comp}_LIBRARY ) + get_filename_component(NetCDF_${_comp}_LIBRARY ${NetCDF_${_comp}_LIBRARY} ABSOLUTE) + set(NetCDF_${_comp}_LIBRARY ${NetCDF_${_comp}_LIBRARY} CACHE STRING "NetCDF ${_comp} library" FORCE) + message(DEBUG "NetCDF_${_comp}_LIBRARY: ${NetCDF_${_comp}_LIBRARY}") + + if( NetCDF_${_comp}_LIBRARY ) + if( NetCDF_${_comp}_LIBRARY MATCHES ".a$" ) + set( NetCDF_${_comp}_LIBRARY_SHARED FALSE ) + set( _library_type STATIC) + else() + list( APPEND NetCDF_LIBRARIES ${NetCDF_${_comp}_LIBRARY} ) + set( NetCDF_${_comp}_LIBRARY_SHARED TRUE ) + set( _library_type SHARED) + endif() + endif() + + #Use nc-config to set per-component LIBRARIES variable if possible + netcdf_config( ${NetCDF_${_comp}_CONFIG_EXECUTABLE} ${_${_comp}_libs_flag} _val ) + if( _val ) + set( NetCDF_${_comp}_LIBRARIES ${_val} ) + if(NOT NetCDF_${_comp}_LIBRARY_SHARED AND NOT NetCDF_${_comp}_FOUND) #Static targets should use nc_config to get a proper link line with all necessary static targets. + list( APPEND NetCDF_LIBRARIES ${NetCDF_${_comp}_LIBRARIES} ) + endif() + else() + set( NetCDF_${_comp}_LIBRARIES ${NetCDF_${_comp}_LIBRARY} ) + if(NOT NetCDF_${_comp}_LIBRARY_SHARED) + message(SEND_ERROR "Unable to properly find NetCDF. Found static libraries at: ${NetCDF_${_comp}_LIBRARY} but could not run nc-config: ${NetCDF_CONFIG_EXECUTABLE}") + endif() + endif() + + #Use nc-config to set per-component INCLUDE_DIRS variable if possible + netcdf_config( ${NetCDF_${_comp}_CONFIG_EXECUTABLE} ${_${_comp}_includes_flag} _val ) + if( _val ) + string( REPLACE " " ";" _val ${_val} ) + set( NetCDF_${_comp}_INCLUDE_DIRS ${_val} ) + else() + set( NetCDF_${_comp}_INCLUDE_DIRS ${NetCDF_${_comp}_INCLUDE_DIR} ) + endif() + + if( NetCDF_${_comp}_LIBRARIES AND NetCDF_${_comp}_INCLUDE_DIRS ) + set( ${CMAKE_FIND_PACKAGE_NAME}_${_arg_${_COMP}}_FOUND TRUE ) + if (NOT TARGET NetCDF::NetCDF_${_comp}) + add_library(NetCDF::NetCDF_${_comp} ${_library_type} IMPORTED) + set_target_properties(NetCDF::NetCDF_${_comp} PROPERTIES + IMPORTED_LOCATION ${NetCDF_${_comp}_LIBRARY} + INTERFACE_INCLUDE_DIRECTORIES "${NetCDF_${_comp}_INCLUDE_DIRS}" + INTERFACE_LINK_LIBRARIES ${NetCDF_${_comp}_LIBRARIES} ) + if( NOT _comp MATCHES "^(C)$" ) + target_link_libraries(NetCDF::NetCDF_${_comp} INTERFACE NetCDF::NetCDF_C) + endif() + if(MPI_${_comp}_FOUND) + target_link_libraries(NetCDF::NetCDF_${_comp} INTERFACE MPI::MPI_${_comp}) + endif() + endif() + endif() +endforeach() +if(NetCDF_LIBRARIES AND NetCDF_${_comp}_LIBRARY_SHARED) + list(REMOVE_DUPLICATES NetCDF_LIBRARIES) +endif() +set(NetCDF_LIBRARIES "${NetCDF_LIBRARIES}" CACHE STRING "NetCDF library targets" FORCE) + +## Find version via netcdf-config if possible +if (NetCDF_INCLUDE_DIRS) + if( NetCDF_C_CONFIG_EXECUTABLE ) + netcdf_config( ${NetCDF_C_CONFIG_EXECUTABLE} --version _vers ) + if( _vers ) + string(REGEX REPLACE ".* ((([0-9]+)\\.)+([0-9]+)).*" "\\1" NetCDF_VERSION "${_vers}" ) + endif() + else() + foreach( _dir IN LISTS NetCDF_INCLUDE_DIRS) + if( EXISTS "${_dir}/netcdf_meta.h" ) + file(STRINGS "${_dir}/netcdf_meta.h" _netcdf_version_lines + REGEX "#define[ \t]+NC_VERSION_(MAJOR|MINOR|PATCH|NOTE)") + string(REGEX REPLACE ".*NC_VERSION_MAJOR *\([0-9]*\).*" "\\1" _netcdf_version_major "${_netcdf_version_lines}") + string(REGEX REPLACE ".*NC_VERSION_MINOR *\([0-9]*\).*" "\\1" _netcdf_version_minor "${_netcdf_version_lines}") + string(REGEX REPLACE ".*NC_VERSION_PATCH *\([0-9]*\).*" "\\1" _netcdf_version_patch "${_netcdf_version_lines}") + string(REGEX REPLACE ".*NC_VERSION_NOTE *\"\([^\"]*\)\".*" "\\1" _netcdf_version_note "${_netcdf_version_lines}") + set(NetCDF_VERSION "${_netcdf_version_major}.${_netcdf_version_minor}.${_netcdf_version_patch}${_netcdf_version_note}") + unset(_netcdf_version_major) + unset(_netcdf_version_minor) + unset(_netcdf_version_patch) + unset(_netcdf_version_note) + unset(_netcdf_version_lines) + endif() + endforeach() + endif() +endif () + +## Finalize find_package +include(FindPackageHandleStandardArgs) + +if(NOT NetCDF_FOUND OR _new_search_components) + find_package_handle_standard_args( ${CMAKE_FIND_PACKAGE_NAME} + REQUIRED_VARS NetCDF_INCLUDE_DIRS NetCDF_LIBRARIES + VERSION_VAR NetCDF_VERSION + HANDLE_COMPONENTS ) +endif() + +foreach( _comp IN LISTS _search_components ) + if( NetCDF_${_comp}_FOUND ) + #Record found components to avoid duplication in NetCDF_LIBRARIES for static libraries + set(NetCDF_${_comp}_FOUND ${NetCDF_${_comp}_FOUND} CACHE BOOL "NetCDF ${_comp} Found" FORCE) + #Set a per-package, per-component found variable to communicate between multiple calls to find_package() + set(${PROJECT_NAME}_NetCDF_${_comp}_FOUND True) + endif() +endforeach() + +if( ${CMAKE_FIND_PACKAGE_NAME}_FOUND AND NOT ${CMAKE_FIND_PACKAGE_NAME}_FIND_QUIETLY AND _new_search_components) + message( STATUS "Find${CMAKE_FIND_PACKAGE_NAME} defines targets:" ) + message( STATUS " - NetCDF_VERSION [${NetCDF_VERSION}]") + message( STATUS " - NetCDF_PARALLEL [${NetCDF_PARALLEL}]") + foreach( _comp IN LISTS _new_search_components ) + string( TOUPPER "${_comp}" _COMP ) + message( STATUS " - NetCDF_${_comp}_CONFIG_EXECUTABLE [${NetCDF_${_comp}_CONFIG_EXECUTABLE}]") + if( ${CMAKE_FIND_PACKAGE_NAME}_${_arg_${_COMP}}_FOUND ) + get_filename_component(_root ${NetCDF_${_comp}_INCLUDE_DIR}/.. ABSOLUTE) + if( NetCDF_${_comp}_LIBRARY_SHARED ) + message( STATUS " - NetCDF::NetCDF_${_comp} [SHARED] [Root: ${_root}] Lib: ${NetCDF_${_comp}_LIBRARY} ") + else() + message( STATUS " - NetCDF::NetCDF_${_comp} [STATIC] [Root: ${_root}] Lib: ${NetCDF_${_comp}_LIBRARY} ") + endif() + endif() + endforeach() +endif() + +foreach( _prefix NetCDF NetCDF4 NETCDF NETCDF4 ${CMAKE_FIND_PACKAGE_NAME} ) + set( ${_prefix}_INCLUDE_DIRS ${NetCDF_INCLUDE_DIRS} ) + set( ${_prefix}_LIBRARIES ${NetCDF_LIBRARIES}) + set( ${_prefix}_VERSION ${NetCDF_VERSION} ) + set( ${_prefix}_FOUND ${${CMAKE_FIND_PACKAGE_NAME}_FOUND} ) + set( ${_prefix}_CONFIG_EXECUTABLE ${NetCDF_CONFIG_EXECUTABLE} ) + set( ${_prefix}_PARALLEL ${NetCDF_PARALLEL} ) + + foreach( _comp ${_search_components} ) + string( TOUPPER "${_comp}" _COMP ) + set( _arg_comp ${_arg_${_COMP}} ) + set( ${_prefix}_${_comp}_FOUND ${${CMAKE_FIND_PACKAGE_NAME}_${_arg_comp}_FOUND} ) + set( ${_prefix}_${_COMP}_FOUND ${${CMAKE_FIND_PACKAGE_NAME}_${_arg_comp}_FOUND} ) + set( ${_prefix}_${_arg_comp}_FOUND ${${CMAKE_FIND_PACKAGE_NAME}_${_arg_comp}_FOUND} ) + + set( ${_prefix}_${_comp}_LIBRARIES ${NetCDF_${_comp}_LIBRARIES} ) + set( ${_prefix}_${_COMP}_LIBRARIES ${NetCDF_${_comp}_LIBRARIES} ) + set( ${_prefix}_${_arg_comp}_LIBRARIES ${NetCDF_${_comp}_LIBRARIES} ) + + set( ${_prefix}_${_comp}_INCLUDE_DIRS ${NetCDF_${_comp}_INCLUDE_DIRS} ) + set( ${_prefix}_${_COMP}_INCLUDE_DIRS ${NetCDF_${_comp}_INCLUDE_DIRS} ) + set( ${_prefix}_${_arg_comp}_INCLUDE_DIRS ${NetCDF_${_comp}_INCLUDE_DIRS} ) + endforeach() +endforeach() \ No newline at end of file diff --git a/tools/mksurfdata_esmf/download_input_data b/tools/mksurfdata_esmf/download_input_data new file mode 100755 index 0000000000..c7f9918247 --- /dev/null +++ b/tools/mksurfdata_esmf/download_input_data @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +"""Download input data for running mksurfdata_esmf""" + +import os +import sys + +_CTSM_PYTHON = os.path.join(os.path.dirname(os.path.realpath(__file__)), + os.pardir, + os.pardir, + 'python') +sys.path.insert(1, _CTSM_PYTHON) + +from ctsm import add_cime_to_path + +from ctsm.mksurfdata_download_input_data import main + +if __name__ == "__main__": + main() diff --git a/tools/mksurfdata_esmf/gen_mksurfdata_build b/tools/mksurfdata_esmf/gen_mksurfdata_build new file mode 100755 index 0000000000..974c1929a5 --- /dev/null +++ b/tools/mksurfdata_esmf/gen_mksurfdata_build @@ -0,0 +1,182 @@ +#! /bin/bash -f + +#---------------------------------------------------------------------- +# Usage subroutine +usage() { + echo "" + echo "***********************************************************************" + echo "usage:" + echo "./gen_mksurfdata_build" + echo "" + echo "valid arguments: " + echo "[-h|--help] " + echo " Displays this help message" + echo "[-v|--verbose] " + echo " Run in verbose mode" + echo "[-b|--blddir ] " + echo " Overrides default, which is /tool_bld in the same directory as ./gen_mksurfdata_build" + echo "[-m|--machine ] " + echo " Overrides default MACH" + echo "***********************************************************************" +} + + +# Current working directory: the location of ./gen_mksurfdata_build +cwd=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) + +# Default settings +verbose="No" +blddir=$cwd/tool_bld # may overwrite this default with command-line option (below) + +# Define what machine to use that's been ported to cime +# May overwrite this default with command-line option --machine +hostname=`hostname --short` +case $hostname in + derecho* | dec* ) + export MACH="derecho" + pio_iotype=1 + ;; + casper* ) + export MACH="casper" + pio_iotype=1 + ;; + izumi*) + export MACH="izumi" + pio_iotype=2 + ;; + hobart*) + export MACH="hobart" + pio_iotype=2 + ;; + ## Other machines + ## Assumption: pnetcdf is off; therefore, pio_iotype = 2 + *) + export MACH="$hostname" + pio_iotype=2 + ;; +esac + +# Parse command-line options +while [ $# -gt 0 ]; do + case $1 in + -h|--help ) + usage + exit 0 + ;; + -v|--verbose ) + verbose="YES" + ;; + -b|--blddir ) + blddir=$2 + shift + ;; + -m|--machine ) + MACH=$2 + shift + ;; + * ) + echo "ERROR:: invalid argument sent in: $2" + usage + exit 1 + ;; + esac + shift +done + +# Create /tool_bld directory +if [ "$verbose" = "YES" ]; then + echo "cime Machine is: $MACH..." +fi +if [ -d "$blddir" ]; then + echo "Build directory exists so will skip the configure and cmake steps..." + existing_bld=YES +else + if [ "$verbose" = "YES" ]; then echo "Build directory does NOT exist so do the configure and cmake steps"; fi + existing_bld=No +fi +if [ "$existing_bld" = "No" ]; then + mkdir $blddir +fi +cd $blddir + +# Write pio_iotype to file with name pio_iotype.txt +pio_iotype_filepath=../pio_iotype.txt # one up from /tool_bld +if [ ! -f "$pio_iotype_filepath" ]; then + echo 'VALUE OF pio_iotype WRITTEN BY gen_mksurfdata_build AND USED BY mksurfdata (i.e. THE FORTRAN EXECUTABLE):' > $pio_iotype_filepath + echo $pio_iotype >> $pio_iotype_filepath +else + echo "Use existing $pio_iotype_filepath file" +fi + +# +# If NOT an existing build, run the configure +# +if [ "$existing_bld" = "No" ]; then + # Run the cime configure tool to figure out what modules need to be loaded + if [ "$verbose" = "YES" ]; then + echo "Run cime configure for machine $MACH..." + fi + # You can specify the non-default compiler and mpi-library by adding --compiler and --mpilib settings + if [ -z "$COMPILER" ] || [ -z "$MPILIB" ]; then + if [ "$verbose" = "YES" ]; then echo "configure for the default MPI-library and compiler..."; fi + options="" + else + if [ "$verbose" = "YES" ]; then echo "configure for the specific MPILIB=$MPILIB and COMPILER=$COMPILER..."; fi + options="-compiler $COMPILER --mpilib $MPILIB" + fi + if [ "$verbose" != "YES" ]; then + options="$options --silent" + fi + $cwd/../../cime/CIME/scripts/configure --macros-format CMake --machine $MACH $options + + if [ $? != 0 ]; then + echo "Error doing configure for machine name: $MACH" + exit 1 + fi +fi + +# +# Create the machine environment (always) +# +. ./.env_mach_specific.sh +if [ $? != 0 ]; then + echo "Error sourcing the env_mach_specific.sh file" + exit 1 +fi +if [ "$verbose" = "YES" ]; then echo "COMPILER = $COMPILER, MPILIB = $MPILIB, DEBUG = $DEBUG, OS = $OS"; fi +if [ -z "$PIO" ]; then + echo "The PIO directory for the PIO build is required and was not set in the configure" + echo "Make sure a PIO build is provided for $MACH_$COMPILER with $MPILIB in config_machines" + exit 1 +fi + +# Build the cmake files (only if not an existing build) +if [ "$existing_bld" = "No" ]; then + if [ "$verbose" = "YES" ]; then + echo "Do the cmake build..." + options="-Wno-dev" + else + options="-Wno-dev -Wno-error=dev -Wno-deprecated -Wno-error=deprecated" + fi + CC=mpicc FC=mpif90 cmake $options -DCMAKE_BUILD_TYPE=Debug $cwd/src + if [ $? != 0 ]; then + echo "Error doing cmake for $MACH $MPILIB $COMPILER" + exit 1 + fi +fi + +# Build the executable (always) +if [ "$verbose" = "YES" ]; then + echo "Build mksurfdata_esmf..." + make VERBOSE=1 +else + make +fi +if [ $? != 0 ]; then + echo "Error doing make for $MACH $MPILIB $COMPILER" + exit 1 +fi +echo "" +echo "" +echo "" +echo "Successfully created mksurfdata_esmf executable for: ${MACH}_${COMPILER} for $MPILIB library" diff --git a/tools/mksurfdata_esmf/gen_mksurfdata_jobscript_multi b/tools/mksurfdata_esmf/gen_mksurfdata_jobscript_multi new file mode 100755 index 0000000000..be2cc7a00d --- /dev/null +++ b/tools/mksurfdata_esmf/gen_mksurfdata_jobscript_multi @@ -0,0 +1,34 @@ +#!/usr/bin/env python3 +""" +This is a just top-level skeleton script that calls +gen_mksurfdata_jobscript_multi.py. +The original code (gen_mksurfdata_jobscript_multi.py) is located under the +python/ctsm/toolchain folder. + +For full instructions on how to run the code and different options, +please check the python/ctsm/toolchain/gen_mksurfdata_jobscript_multi.py file. + +To run this script the following packages are required: + - netCDF4 +---------------------------------------------------------------- +To see all available options for gen_mksurfdata_jobscript_multi + ./gen_mksurfdata_jobscript_multi --help +---------------------------------------------------------------- +Instructions for running using the conda python environments: +../../py_env_create +conda activate ctsm_py +""" + +import os +import sys + +# -- add python/ctsm to path +_CTSM_PYTHON = os.path.join( + os.path.dirname(os.path.realpath(__file__)), os.pardir, os.pardir, "python" +) +sys.path.insert(1, _CTSM_PYTHON) + +from ctsm.toolchain.gen_mksurfdata_jobscript_multi import main + +if __name__ == "__main__": + main() diff --git a/tools/mksurfdata_esmf/gen_mksurfdata_jobscript_single b/tools/mksurfdata_esmf/gen_mksurfdata_jobscript_single new file mode 100755 index 0000000000..a9b510962c --- /dev/null +++ b/tools/mksurfdata_esmf/gen_mksurfdata_jobscript_single @@ -0,0 +1,34 @@ +#!/usr/bin/env python3 +""" +This is a just top-level skeleton script that calls +gen_mksurfdata_jobscript_single.py. +The original code (gen_mksurfdata_jobscript_single.py) is located under the +python/ctsm/toolchain folder. + +For full instructions on how to run the code and different options, +please check the python/ctsm/toolchain/gen_mksurfdata_jobscript_single.py file. + +To run this script the following packages are required: + - netCDF4 +---------------------------------------------------------------- +To see all available options for gen_mksurfdata_jobscript_single + ./gen_mksurfdata_jobscript_single --help +---------------------------------------------------------------- +Instructions for running using the conda python environments: +../../py_env_create +conda activate ctsm_py +""" + +import os +import sys + +# -- add python/ctsm to path +_CTSM_PYTHON = os.path.join( + os.path.dirname(os.path.realpath(__file__)), os.pardir, os.pardir, "python" +) +sys.path.insert(1, _CTSM_PYTHON) + +from ctsm.toolchain.gen_mksurfdata_jobscript_single import main + +if __name__ == "__main__": + main() diff --git a/tools/mksurfdata_esmf/gen_mksurfdata_namelist b/tools/mksurfdata_esmf/gen_mksurfdata_namelist new file mode 100755 index 0000000000..e3688f7cb0 --- /dev/null +++ b/tools/mksurfdata_esmf/gen_mksurfdata_namelist @@ -0,0 +1,34 @@ +#!/usr/bin/env python3 +""" +This is a just top-level skeleton script that calls +gen_mksurfdata_namelist.py. +The original code (gen_mksurfdata_namelist.py) is located under the +python/ctsm/toolchain folder. + +For full instructions on how to run the code and different options, +please check the python/ctsm/toolchain/gen_mksurfdata_namelist.py file. + +To run this script the following packages are required: + - netCDF4 +---------------------------------------------------------------- +To see all available options for gen_mksurfdata_namelist + ./gen_mksurfdata_namelist --help +---------------------------------------------------------------- +Instructions for running using the conda python environments: +../../py_env_create +conda activate ctsm_py +""" + +import os +import sys + +# -- add python/ctsm to path +_CTSM_PYTHON = os.path.join( + os.path.dirname(os.path.realpath(__file__)), os.pardir, os.pardir, "python" +) +sys.path.insert(1, _CTSM_PYTHON) + +from ctsm.toolchain.gen_mksurfdata_namelist import main + +if __name__ == "__main__": + main() diff --git a/tools/mksurfdata_esmf/gen_mksurfdata_namelist.xml b/tools/mksurfdata_esmf/gen_mksurfdata_namelist.xml new file mode 100644 index 0000000000..32fb7d51bf --- /dev/null +++ b/tools/mksurfdata_esmf/gen_mksurfdata_namelist.xml @@ -0,0 +1,351 @@ + + + + + + + + + + + + + lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c20230226/mksrf_pftlaihgt_ctsm52_histLUH2_2005.c20230226.nc + lnd/clm2/mappingdata/grids/UNSTRUCTgrid_0.25x0.25_nomask_cdf5_c200129.nc + + + lnd/clm2/rawdata/pftcftdynharv.0.05x0.05.LUH2.histsimyr2005.c190116/mksrf_lai_histclm52deg005_earthstatmirca_2005.cdf5.c220228.nc + lnd/clm2/mappingdata/grids/UNSTRUCTgrid_3x3min_nomask_cdf5_c200129.nc + + + + + + + + + + lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c20230226/mksrf_soilcolor_ctsm52_histLUH2_2005.c20230226.nc + lnd/clm2/mappingdata/grids/UNSTRUCTgrid_0.25x0.25_nomask_cdf5_c200129.nc + + + lnd/clm2/rawdata/pftcftdynharv.0.05x0.05.LUH2.histsimyr2005.c190116/mksrf_soilcolor_histclm52deg005_earthstatmirca_2005.cdf5.c220228.nc + lnd/clm2/mappingdata/grids/UNSTRUCTgrid_3x3min_nomask_cdf5_c200129.nc + + + + + + lnd/clm2/rawdata/mksrf_soil_mapunits_5x5min_WISE.c220330.nc + lnd/clm2/rawdata/mksrf_soil_lookup.10level.WISE.c220330.nc + lnd/clm2/mappingdata/grids/UNSTRUCTgrid_5x5min_nomask_cdf5_c200129.nc + + + lnd/clm2/rawdata/mksrf_soil_mapunits_30sec_WISE.c220330.nc + lnd/clm2/rawdata/mksrf_soil_lookup.10level.WISE.c220330.nc + lnd/clm2/rawdata/mksrf_soil_mapunits_30sec_WISE.c220330.nc + + + + + + lnd/clm2/rawdata/mksrf_fmax_0.125x0.125_c200220.nc + lnd/clm2/mappingdata/grids/UNSTRUCTgrid_0.125x0.125_nomask_cdf5_c200129.nc + + + + + + + + + + + + lnd/clm2/mappingdata/grids/UNSTRUCTgrid_3x3min_nomask_cdf5_c200129.nc + + + + + + + + lnd/clm2/rawdata/mksrf_LakePnDepth_3x3min_simyr2017_MODISgrid.cdf5.c200305.nc + lnd/clm2/mappingdata/grids/UNSTRUCTgrid_3x3min_nomask_cdf5_c200129.nc + + + + + + lnd/clm2/rawdata/mksrf_lanwat.050425.nc + lnd/clm2/mappingdata/grids/UNSTRUCTgrid_0.5x0.5_nomask_cdf5_c200129.nc + + + + + + + + + + lnd/clm2/rawdata/mksrf_vocef_0.5x0.5_simyr2000.c110531.nc + lnd/clm2/mappingdata/grids/UNSTRUCTgrid_0.5x0.5_nomask_cdf5_c200129.nc + + + + + + + + + + + + lnd/clm2/mappingdata/grids/UNSTRUCTgrid_3x3min_nomask_cdf5_c200129.nc + + + + + + + lnd/clm2/rawdata/mksrf_topo.10min.cdf5.c220201.nc + lnd/clm2/mappingdata/grids/UNSTRUCTgrid_10x10min_nomask_cdf5_c200129.nc + + + + + + + + + + + + + lnd/clm2/rawdata/mksrf_glacier_3x3min_simyr2000.c20210708.nc + lnd/clm2/mappingdata/grids/UNSTRUCTgrid_3x3min_nomask_cdf5_c200129.nc + + + + + + lnd/clm2/rawdata/mksrf_GlacierRegion_10x10min_nomask_cd5_c220131.nc + lnd/clm2/mappingdata/grids/UNSTRUCTgrid_10x10min_nomask_cdf5_c200129.nc + + + + + + + + + + lnd/clm2/rawdata/mksrf_gdp_0.5x0.5_AVHRR_simyr2000.c130228.nc + lnd/clm2/mappingdata/grids/UNSTRUCTgrid_0.5x0.5_nomask_cdf5_c200129.nc + + + lnd/clm2/rawdata/mksrf_gdp_0.5x0.5_zerogdp.cdf5.c200413.nc + lnd/clm2/mappingdata/grids/UNSTRUCTgrid_0.5x0.5_nomask_cdf5_c200129.nc + + + + + + lnd/clm2/rawdata/mksrf_peatf_0.5x0.5_AVHRR_simyr2000.c130228.nc + lnd/clm2/mappingdata/grids/UNSTRUCTgrid_0.5x0.5_nomask_cdf5_c200129.nc + + + + + + lnd/clm2/rawdata/mksf_soilthk_5x5min_ORNL-Soil_simyr1900-2015_c170630.nc + lnd/clm2/mappingdata/grids/UNSTRUCTgrid_5x5min_nomask_cdf5_c200129.nc + + + + + + lnd/clm2/rawdata/mksrf_abm_0.5x0.5_AVHRR_simyr2000.c130201.nc + lnd/clm2/mappingdata/grids/UNSTRUCTgrid_0.5x0.5_nomask_cdf5_c200129.nc + + + lnd/clm2/rawdata/mksrf_abm_0.5x0.5_missingabm.cdf5.c200413.nc + lnd/clm2/mappingdata/grids/UNSTRUCTgrid_0.5x0.5_nomask_cdf5_c200129.nc + + + + + + + + + + lnd/clm2/rawdata/mksrf_topostats_1km-merge-10min_HYDRO1K-merge-nomask_simyr2000.c130402.nc + lnd/clm2/mappingdata/grids/UGRID_1km-merge-10min_HYDRO1K-merge-nomask_cdf5_c130402.nc + + + + + + + + + + lnd/clm2/rawdata/mksrf_vic_0.9x1.25_GRDC_simyr2000.c130307.nc + lnd/clm2/mappingdata/grids/UNSTRUCTgrid_0.9x1.25_nomask_cdf5_c200129.nc + + + + + + + + + + + lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.noanthro.c20230226/mksrf_landuse_ctsm52_noanthroLUH2_1.c20230226.nc + lnd/clm2/mappingdata/grids/UNSTRUCTgrid_0.25x0.25_nomask_cdf5_c200129.nc + lnd/clm2/rawdata/lake_area/mksurf_lake_0.05x0.05_hist_clm5_hydrolakes_1850.cdf5.c20220325.nc + lnd/clm2/rawdata/mksrf_urban_0.05x0.05_zerourbanpct.cdf5.c181014.nc + + + + lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c20230226/mksrf_landuse_ctsm52_histLUH2_1850.c20230226.nc + lnd/clm2/mappingdata/grids/UNSTRUCTgrid_0.25x0.25_nomask_cdf5_c200129.nc + lnd/clm2/rawdata/lake_area/mksurf_lake_0.05x0.05_hist_clm5_hydrolakes_1850.cdf5.c20220325.nc + lnd/clm2/rawdata/gao_oneill_urban/historical/urban_properties_GaoOneil_05deg_ThreeClass_1850_cdf5_c20220910.nc + + + + lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c20230226/mksrf_landuse_ctsm52_histLUH2_2000.c20230226.nc + lnd/clm2/mappingdata/grids/UNSTRUCTgrid_0.25x0.25_nomask_cdf5_c200129.nc + lnd/clm2/rawdata/lake_area/mksurf_lake_0.05x0.05_hist_clm5_hydrolakes_2000.cdf5.c20220325.nc + lnd/clm2/rawdata/gao_oneill_urban/historical/urban_properties_GaoOneil_05deg_ThreeClass_2000_cdf5_c20220910.nc + + + + lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c20230226/mksrf_landuse_ctsm52_histLUH2_2005.c20230226.nc + lnd/clm2/mappingdata/grids/UNSTRUCTgrid_0.25x0.25_nomask_cdf5_c200129.nc + lnd/clm2/rawdata/lake_area/mksurf_lake_0.05x0.05_hist_clm5_hydrolakes_2005.cdf5.c20220325.nc + lnd/clm2/rawdata/gao_oneill_urban/historical/urban_properties_GaoOneil_05deg_ThreeClass_2005_cdf5_c20220910.nc + + + + lnd/clm2/rawdata/pftcftdynharv.0.05x0.05.LUH2.histsimyr2005.c190116/mksrf_landuse_clm52deg005_histLUH2_2005.cdf5.c190119.nc + lnd/clm2/mappingdata/grids/UNSTRUCTgrid_3x3min_nomask_cdf5_c200129.nc + lnd/clm2/rawdata/lake_area/mksurf_lake_0.05x0.05_hist_clm5_hydrolakes_2005.cdf5.c20220325.nc + lnd/clm2/rawdata/gao_oneill_urban/historical/urban_properties_GaoOneil_05deg_ThreeClass_2005_cdf5_c20220910.nc + + + + + lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1850.c20230226/mksrf_landuse_ctsm52_histLUH2_%y.c20230226.nc + lnd/clm2/mappingdata/grids/UNSTRUCTgrid_0.25x0.25_nomask_cdf5_c200129.nc + lnd/clm2/rawdata/lake_area/mksurf_lake_0.05x0.05_hist_clm5_hydrolakes_1850.cdf5.c20220325.nc + lnd/clm2/rawdata/gao_oneill_urban/historical/urban_properties_GaoOneil_05deg_ThreeClass_1850_cdf5_c20220910.nc + + + + + lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c20230226/mksrf_landuse_ctsm52_histLUH2_%y.c20230226.nc + lnd/clm2/mappingdata/grids/UNSTRUCTgrid_0.25x0.25_nomask_cdf5_c200129.nc + lnd/clm2/rawdata/lake_area/mksurf_lake_0.05x0.05_hist_clm5_hydrolakes_%y.cdf5.c20220325.nc + lnd/clm2/rawdata/gao_oneill_urban/historical/urban_properties_GaoOneil_05deg_ThreeClass_%y_cdf5_c20220910.nc + + + + + + + + + + + lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2015-2100.c20230226/mksrf_landuse_ctsm52_SSP1-2.6_%y.c20230226.nc + lnd/clm2/mappingdata/grids/UNSTRUCTgrid_0.25x0.25_nomask_cdf5_c200129.nc + lnd/clm2/rawdata/lake_area/mksurf_lake_0.05x0.05_hist_clm5_hydrolakes_%y.cdf5.c20220325.nc + lnd/clm2/rawdata/gao_oneill_urban/ssp1/urban_properties_GaoOneil_05deg_ThreeClass_ssp1_%y_cdf5_c20220910.nc + + + lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2100-2300.c20230226/mksrf_landuse_ctsm52_SSP1-2.6_%y.c20230226.nc + lnd/clm2/mappingdata/grids/UNSTRUCTgrid_0.25x0.25_nomask_cdf5_c200129.nc + lnd/clm2/rawdata/lake_area/mksurf_lake_0.05x0.05_hist_clm5_hydrolakes_2100.cdf5.c20220325.nc + lnd/clm2/rawdata/gao_oneill_urban/ssp1/urban_properties_GaoOneil_05deg_ThreeClass_ssp1_2100_cdf5_c20220910.nc + + + + lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2015-2100.c20230226/mksrf_landuse_ctsm52_SSP1-1.9_%y.c20230226.nc + lnd/clm2/mappingdata/grids/UNSTRUCTgrid_0.25x0.25_nomask_cdf5_c200129.nc + lnd/clm2/rawdata/lake_area/mksurf_lake_0.05x0.05_hist_clm5_hydrolakes_%y.cdf5.c20220325.nc + lnd/clm2/rawdata/gao_oneill_urban/ssp1/urban_properties_GaoOneil_05deg_ThreeClass_ssp1_%y_cdf5_c20220910.nc + + + + lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2015-2100.c20230226/mksrf_landuse_ctsm52_SSP2-4.5_%y.c20230226.nc + lnd/clm2/mappingdata/grids/UNSTRUCTgrid_0.25x0.25_nomask_cdf5_c200129.nc + lnd/clm2/rawdata/lake_area/mksurf_lake_0.05x0.05_hist_clm5_hydrolakes_%y.cdf5.c20220325.nc + lnd/clm2/rawdata/gao_oneill_urban/ssp2/urban_properties_GaoOneil_05deg_ThreeClass_ssp2_%y_cdf5_c20220910.nc + + + + lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2015-2100.c20230226/mksrf_landuse_ctsm52_SSP3-7.0_%y.c20230226.nc + lnd/clm2/mappingdata/grids/UNSTRUCTgrid_0.25x0.25_nomask_cdf5_c200129.nc + lnd/clm2/rawdata/lake_area/mksurf_lake_0.05x0.05_hist_clm5_hydrolakes_%y.cdf5.c20220325.nc + lnd/clm2/rawdata/gao_oneill_urban/ssp3/urban_properties_GaoOneil_05deg_ThreeClass_ssp3_%y_cdf5_c20220910.nc + + + + lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2015-2100.c20230226/mksrf_landuse_ctsm52_SSP4-3.4_%y.c20230226.nc + lnd/clm2/mappingdata/grids/UNSTRUCTgrid_0.25x0.25_nomask_cdf5_c200129.nc + lnd/clm2/rawdata/lake_area/mksurf_lake_0.05x0.05_hist_clm5_hydrolakes_%y.cdf5.c20220325.nc + lnd/clm2/rawdata/gao_oneill_urban/ssp4/urban_properties_GaoOneil_05deg_ThreeClass_ssp4_%y_cdf5_c20220910.nc + + + + lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2015-2100.c20230226/mksrf_landuse_ctsm52_SSP4-6.0_%y.c20230226.nc + lnd/clm2/mappingdata/grids/UNSTRUCTgrid_0.25x0.25_nomask_cdf5_c200129.nc + lnd/clm2/rawdata/lake_area/mksurf_lake_0.05x0.05_hist_clm5_hydrolakes_%y.cdf5.c20220325.nc + lnd/clm2/rawdata/gao_oneill_urban/ssp4/urban_properties_GaoOneil_05deg_ThreeClass_ssp4_%y_cdf5_c20220910.nc + + + + lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2015-2100.c20230226/mksrf_landuse_ctsm52_SSP5-8.5_%y.c20230226.nc + lnd/clm2/mappingdata/grids/UNSTRUCTgrid_0.25x0.25_nomask_cdf5_c200129.nc + lnd/clm2/rawdata/lake_area/mksurf_lake_0.05x0.05_hist_clm5_hydrolakes_%y.cdf5.c20220325.nc + lnd/clm2/rawdata/gao_oneill_urban/ssp5/urban_properties_GaoOneil_05deg_ThreeClass_ssp5_%y_cdf5_c20220910.nc + + + lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2100-2300.c20230226/mksrf_landuse_ctsm52_SSP5-8.5_%y.c20230226.nc + lnd/clm2/mappingdata/grids/UNSTRUCTgrid_0.25x0.25_nomask_cdf5_c200129.nc + lnd/clm2/rawdata/lake_area/mksurf_lake_0.05x0.05_hist_clm5_hydrolakes_2100.cdf5.c20220325.nc + lnd/clm2/rawdata/gao_oneill_urban/ssp5/urban_properties_GaoOneil_05deg_ThreeClass_ssp5_2100_cdf5_c20220910.nc + + + + lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2015-2100.c20230226/mksrf_landuse_ctsm52_SSP5-3.4_%y.c20230226.nc + lnd/clm2/mappingdata/grids/UNSTRUCTgrid_0.25x0.25_nomask_cdf5_c200129.nc + lnd/clm2/rawdata/lake_area/mksurf_lake_0.05x0.05_hist_clm5_hydrolakes_%y.cdf5.c20220325.nc + lnd/clm2/rawdata/gao_oneill_urban/ssp5/urban_properties_GaoOneil_05deg_ThreeClass_ssp5_%y_cdf5_c20220910.nc + + + lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2100-2300.c20230226/mksrf_landuse_ctsm52_SSP5-3.4_%y.c20230226.nc + lnd/clm2/mappingdata/grids/UNSTRUCTgrid_0.25x0.25_nomask_cdf5_c200129.nc + lnd/clm2/rawdata/lake_area/mksurf_lake_0.05x0.05_hist_clm5_hydrolakes_2100.cdf5.c20220325.nc + lnd/clm2/rawdata/gao_oneill_urban/ssp5/urban_properties_GaoOneil_05deg_ThreeClass_ssp5_2100_cdf5_c20220910.nc + + + + + + diff --git a/tools/mksurfdata_map/modify_1x1_mexicocityMEX.cfg b/tools/mksurfdata_esmf/modify_1x1_mexicocityMEX.cfg similarity index 89% rename from tools/mksurfdata_map/modify_1x1_mexicocityMEX.cfg rename to tools/mksurfdata_esmf/modify_1x1_mexicocityMEX.cfg index 6eab73a159..191bb1fedb 100644 --- a/tools/mksurfdata_map/modify_1x1_mexicocityMEX.cfg +++ b/tools/mksurfdata_esmf/modify_1x1_mexicocityMEX.cfg @@ -86,6 +86,7 @@ PCT_NATVEG= 0.0 PCT_GLACIER= 0.0 PCT_WETLAND= 0.0 PCT_LAKE = 0.0 +PCT_OCEAN = 0.0 # Section with a list of variables to prcoess [modify_fsurdat_variable_list] @@ -124,13 +125,13 @@ ALB_ROOF_DIF = 0.2 0.2 ALB_WALL_DIR = 0.25 0.25 ALB_WALL_DIF = 0.25 0.25 -# Variabls on nlevurb which is 5 -TK_ROOF = 0.20 0.93 0.93 0.03 0.16 -TK_WALL = 0.88 0.88 0.88 0.88 0.88 -TK_IMPROAD = 0.82 0.82 2.10 2.10 2.10 -CV_ROOF = 1760000.0 1500000.0 1500000.0 250000.0 870000.0 -CV_WALL = 1540000.0 1540000.0 1540000.0 1540000.0 1540000.0 -CV_IMPROAD = 1740000.0 1740000.0 2000000.0 2000000.0 2000000.0 +# Variables on nlevurb which is 10 +TK_ROOF = 0.20 0.93 0.93 0.93 0.93 0.93 0.03 0.03 0.03 0.16 +TK_WALL = 0.88 0.88 0.88 0.88 0.88 0.88 0.88 0.88 0.88 0.88 +TK_IMPROAD = 0.82 0.82 2.10 2.10 2.10 0.00 0.00 0.00 0.00 0.00 +CV_ROOF = 1760000.0 1500000.0 1500000.0 1500000.0 1500000.0 1500000.0 250000.0 250000.0 250000.0 870000.0 +CV_WALL = 1540000.0 1540000.0 1540000.0 1540000.0 1540000.0 1540000.0 1540000.0 1540000.0 1540000.0 1540000.0 +CV_IMPROAD = 1740000.0 1740000.0 2000000.0 2000000.0 2000000.0 0.0 0.0 0.0 0.0 0.0 # Natural and Crop PFT's don't really need to be set, since they have zero area, but # it looks better to do so diff --git a/tools/mksurfdata_map/modify_1x1_urbanc_alpha.cfg b/tools/mksurfdata_esmf/modify_1x1_urbanc_alpha.cfg similarity index 92% rename from tools/mksurfdata_map/modify_1x1_urbanc_alpha.cfg rename to tools/mksurfdata_esmf/modify_1x1_urbanc_alpha.cfg index d704b629bd..bdb27ac43d 100644 --- a/tools/mksurfdata_map/modify_1x1_urbanc_alpha.cfg +++ b/tools/mksurfdata_esmf/modify_1x1_urbanc_alpha.cfg @@ -86,6 +86,7 @@ PCT_NATVEG= 0.0 PCT_GLACIER= 0.0 PCT_WETLAND= 0.0 PCT_LAKE = 0.0 +PCT_OCEAN = 0.0 # Section with a list of variables to prcoess [modify_fsurdat_variable_list] @@ -98,6 +99,9 @@ PCT_LAKE = 0.0 # Add variables on the file and assign a new value # can't specify soil_color, max_sat_area or other things that are above. +# URBAN_REGION_ID MUST be set, when there is urban area +URBAN_REGION_ID = 2 + # Variables on numurbl which is 3 CANYON_HWR = 0.42 0.42 0.42 EM_IMPROAD = 0.973 0.973 0.973 @@ -124,13 +128,13 @@ ALB_ROOF_DIF = 0.21 0.21 ALB_WALL_DIR = 0.21 0.21 ALB_WALL_DIF = 0.21 0.21 -# Variabls on nlevurb which is 5 -TK_ROOF = 6.530 0.025 0.230 0.160 0.00 -TK_WALL = 0.610 0.430 0.024 0.160 0.00 -TK_IMPROAD = 1.170 0.300 0.300 0.420 0.00 -CV_ROOF = 2070000.0 7100.0 1500000.0 670000.0 0.0 -CV_WALL = 1250000.0 1400000.0 1300.0 670000.0 0.0 -CV_IMPROAD = 1140000.0 1050000.0 1050000.0 1290000.0 0.0 +# Variabls on nlevurb which is 4 for this site +TK_ROOF = 6.530 0.025 0.230 0.160 +TK_WALL = 0.610 0.430 0.024 0.160 +TK_IMPROAD = 1.170 0.300 0.300 0.420 +CV_ROOF = 2070000.0 7100.0 1500000.0 670000.0 +CV_WALL = 1250000.0 1400000.0 1300.0 670000.0 +CV_IMPROAD = 1140000.0 1050000.0 1050000.0 1290000.0 # Natural and Crop PFT's don't really need to be set, since they have zero area, but # it looks better to do so diff --git a/tools/mksurfdata_map/modify_1x1_vancouverCAN.cfg b/tools/mksurfdata_esmf/modify_1x1_vancouverCAN.cfg similarity index 89% rename from tools/mksurfdata_map/modify_1x1_vancouverCAN.cfg rename to tools/mksurfdata_esmf/modify_1x1_vancouverCAN.cfg index f46593d653..bf3ebe5ee0 100644 --- a/tools/mksurfdata_map/modify_1x1_vancouverCAN.cfg +++ b/tools/mksurfdata_esmf/modify_1x1_vancouverCAN.cfg @@ -86,6 +86,7 @@ PCT_NATVEG= 0.0 PCT_GLACIER= 0.0 PCT_WETLAND= 0.0 PCT_LAKE = 0.0 +PCT_OCEAN = 0.0 # Section with a list of variables to prcoess [modify_fsurdat_variable_list] @@ -124,13 +125,13 @@ ALB_ROOF_DIF = 0.12 0.12 ALB_WALL_DIR = 0.50 0.50 ALB_WALL_DIF = 0.50 0.50 -# Variabls on nlevurb which is 5 -TK_ROOF = 1.40 1.40 1.40 0.03 1.51 -TK_WALL = 1.51 1.51 0.67 0.67 1.51 -TK_IMPROAD = 0.82 0.82 2.10 2.10 2.10 -CV_ROOF = 1760000.0 1760000.0 1760000.0 40000.0 2210000.0 -CV_WALL = 2110000.0 2110000.0 1000000.0 1000000.0 2110000.0 -CV_IMPROAD = 1740000.0 1740000.0 2000000.0 2000000.0 2000000.0 +# Variabls on nlevurb which is 10 +TK_ROOF = 1.40 1.40 1.40 1.40 0.03 1.51 1.51 1.51 1.51 1.51 +TK_WALL = 1.51 1.51 0.67 0.67 0.67 0.67 0.67 0.67 0.67 1.51 +TK_IMPROAD = 0.82 0.82 2.10 2.10 2.10 0.00 0.00 0.00 0.00 0.00 +CV_ROOF = 1760000.0 1760000.0 1760000.0 1760000.0 40000.0 2210000.0 2210000.0 2210000.0 2210000.0 2210000.0 +CV_WALL = 2110000.0 2110000.0 1000000.0 1000000.0 1000000.0 1000000.0 1000000.0 1000000.0 1000000.0 2110000.0 +CV_IMPROAD = 1740000.0 1740000.0 2000000.0 2000000.0 2000000.0 0.0 0.0 0.0 0.0 0.0 # Natural and Crop PFT's don't really need to be set, since they have zero area, but # it looks better to do so diff --git a/tools/mksurfdata_esmf/src/CMakeLists.txt b/tools/mksurfdata_esmf/src/CMakeLists.txt new file mode 100644 index 0000000000..2be063b976 --- /dev/null +++ b/tools/mksurfdata_esmf/src/CMakeLists.txt @@ -0,0 +1,62 @@ +cmake_minimum_required(VERSION 3.10) +project(mksurfdata Fortran) + +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../cmake") +find_package(NetCDF 4.7.4 REQUIRED Fortran) +find_package(ESMF 8.2.0 REQUIRED ) + +set(SRCFILES mkagfirepkmonthMod.F90 + mkchecksMod.F90 + mkdiagnosticsMod.F90 + mkdomainMod.F90 + mkesmfMod.F90 + mkfileMod.F90 + mkgdpMod.F90 + mkglacierregionMod.F90 + mkglcmecMod.F90 + mkharvestMod.F90 + mkindexmapMod.F90 + mkinputMod.F90 + mklaiMod.F90 + mklanwatMod.F90 + mkpeatMod.F90 + mkpioMod.F90 + mkpftMod.F90 + mkpftConstantsMod.F90 + mkpctPftTypeMod.F90 + mkpftUtilsMod.F90 + mksoilcolMod.F90 + mksoilfmaxMod.F90 + mksoiltexMod.F90 + mksoildepthMod.F90 + mktopostatsMod.F90 + mkurbanparMod.F90 + mkutilsMod.F90 + mkvarctl.F90 + mkvarpar.F90 + mkvocefMod.F90 + mkVICparamsMod.F90 + nanMod.F90 + shr_const_mod.F90 + shr_kind_mod.F90 + shr_string_mod.F90 + shr_sys_mod.F90 + mksurfdata.F90) + +add_compile_definitions(PIO2) + +add_library(pnetcdf STATIC IMPORTED) +set_property(TARGET pnetcdf PROPERTY IMPORTED_LOCATION $ENV{PNETCDF}) + +add_library(pioc STATIC IMPORTED) +add_library(piof STATIC IMPORTED) +set_property(TARGET pioc PROPERTY IMPORTED_LOCATION $ENV{PIO}/lib/libpioc.so) +set_property(TARGET piof PROPERTY IMPORTED_LOCATION $ENV{PIO}/lib/libpiof.so) +add_executable(mksurfdata ${SRCFILES}) +target_link_libraries(mksurfdata PRIVATE esmf piof pioc) +target_include_directories (mksurfdata PRIVATE ${ESMF_F90COMPILEPATHS}) +target_include_directories (mksurfdata PRIVATE $ENV{PIO}/include) +target_include_directories (mksurfdata PRIVATE ${PNETCDF}/include) +target_include_directories (mksurfdata PRIVATE ${NETCDF}/include) + +install(TARGETS mksurfdata) diff --git a/tools/mksurfdata_esmf/src/mkVICparamsMod.F90 b/tools/mksurfdata_esmf/src/mkVICparamsMod.F90 new file mode 100644 index 0000000000..5f69152e2d --- /dev/null +++ b/tools/mksurfdata_esmf/src/mkVICparamsMod.F90 @@ -0,0 +1,274 @@ +module mkVICparamsMod + + !----------------------------------------------------------------------- + ! make parameters for VIC + !----------------------------------------------------------------------- + + use ESMF + use pio + use shr_kind_mod , only : r8 => shr_kind_r8, r4 => shr_kind_r4, cl => shr_kind_cl + use shr_sys_mod , only : shr_sys_abort + use mkpioMod , only : mkpio_get_rawdata, pio_iotype, pio_iosystem + use mkesmfMod , only : regrid_rawdata, create_routehandle_r8 + use mkutilsMod , only : chkerr + use mkvarctl , only : root_task, ndiag, spval + use mkchecksMod , only : min_bad + use mkfileMod , only : mkfile_output + use mkdiagnosticsMod , only : output_diagnostics_continuous + + implicit none + private + + public :: mkVICparams ! make VIC parameters + + character(len=*) , parameter :: u_FILE_u = & + __FILE__ + +!=============================================================== +contains +!=============================================================== + + subroutine mkVICparams(file_mesh_i, file_data_i, mesh_o, pioid_o, rc) + ! + ! make VIC parameters + ! + ! input/output variables + character(len=*) , intent(in) :: file_mesh_i ! input mesh file name + character(len=*) , intent(in) :: file_data_i ! input data file name + type(ESMF_Mesh) , intent(in) :: mesh_o ! model mesho + type(file_desc_t), intent(inout) :: pioid_o ! output file descripter + integer , intent(out) :: rc + + ! local variables: + type(ESMF_RouteHandle) :: routehandle + type(ESMF_Mesh) :: mesh_i + type(file_desc_t) :: pioid_i + integer :: ni,no + integer :: ns_i, ns_o + integer :: n,l,k + real(r8), allocatable :: binfl_o(:) ! output VIC b parameter for the Variable Infiltration Capacity Curve (unitless) + real(r8), allocatable :: ws_o(:) ! output VIC Ws parameter for the ARNO curve (unitless) + real(r8), allocatable :: dsmax_o(:) ! output VIC Dsmax parameter for the ARNO curve (mm/day) + real(r8), allocatable :: ds_o(:) ! output VIC Ds parameter for the ARNO curve (unitless) + integer , allocatable :: mask_i(:) + real(r8), allocatable :: rmask_i(:) + real(r8), allocatable :: frac_o(:) + real(r8), allocatable :: data_i(:) ! data on input grid + real(r8), parameter :: min_valid_binfl = 0._r8 + real(r8), parameter :: min_valid_ws = 0._r8 + real(r8), parameter :: min_valid_dsmax = 0._r8 + real(r8), parameter :: min_valid_ds = 0._r8 + integer :: ier,rcode ! error status + character(len=cl) :: errmsg + character(len=*), parameter :: subname = 'mkVICparams' + !----------------------------------------------------------------------- + + rc = ESMF_SUCCESS + + if (root_task) then + write(ndiag,*) + write(ndiag,'(1x,80a1)') ('=',k=1,80) + write(ndiag,*) + write(ndiag,'(a)')'Attempting to make VIC parameters.....' + write(ndiag,'(a)') ' Input file is '//trim(file_data_i) + write(ndiag,'(a)') ' Input mesh file is '//trim(file_mesh_i) + end if + call ESMF_VMLogMemInfo("At start of "//trim(subname)) + + ! Open input data file + rcode = pio_openfile(pio_iosystem, pioid_i, pio_iotype, trim(file_data_i), pio_nowrite) + + ! Read in input mesh + mesh_i = ESMF_MeshCreate(filename=trim(file_mesh_i), fileformat=ESMF_FILEFORMAT_ESMFMESH, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After create mesh_i in "//trim(subname)) + + ! Determine ns_i + call ESMF_MeshGet(mesh_i, numOwnedElements=ns_i, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Determine ns_o + call ESMF_MeshGet(mesh_o, numOwnedElements=ns_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Allocate output variables + allocate (binfl_o(ns_o)) ; binfl_o(:) = spval + allocate (ws_o(ns_o)) ; ws_o(:) = spval + allocate (dsmax_o(ns_o)) ; dsmax_o(:) = spval + allocate (ds_o(ns_o)) ; ds_o(:) = spval + + ! Get the landmask from the file and reset the mesh mask based on that + allocate(rmask_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort() + allocate(mask_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort() + call mkpio_get_rawdata(pioid_i, 'mask', mesh_i, rmask_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + do ni = 1,ns_i + if (rmask_i(ni) > 0._r8) then + mask_i(ni) = 1 + else + mask_i(ni) = 0 + end if + end do + call ESMF_MeshSet(mesh_i, elementMask=mask_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! Create a route handle between the input and output mesh + allocate(frac_o(ns_o)) + call create_routehandle_r8(mesh_i=mesh_i, mesh_o=mesh_o, norm_by_fracs=.true., & + routehandle=routehandle, frac_o=frac_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After create routehandle in "//trim(subname)) + do n = 1, ns_o + if ((frac_o(n) < 0.0) .or. (frac_o(n) > 1.0001)) then + write(errmsg,'(a,f13.5,2x,i4)') "ERROR:: frac_o out of range: ", frac_o(n),n + call shr_sys_abort(trim(errmsg),u_FILE_u,__LINE__) + end if + end do + + ! ----------------------------------------------------------------- + ! Determine binfl + ! ----------------------------------------------------------------- + + ! Read in input data_i for a variety of inputs + allocate(data_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort('allocation error for binfl_i',u_FILE_u,__LINE__) + + ! Read in binfl_i into data_i + call mkpio_get_rawdata(pioid_i, 'binfl', mesh_i, data_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After mkpio_getrawdata in "//trim(subname)) + + ! Regrid binfl_i to binfl_o and check validity of output data + call regrid_rawdata(mesh_i, mesh_o, routehandle, data_i, binfl_o, rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + do no = 1,ns_o + if (frac_o(no) == 0._r8) then + binfl_o(no) = 0.1_r8 + end if + end do + if (min_bad(binfl_o, min_valid_binfl, 'binfl')) then + call shr_sys_abort('error for min_bad',u_FILE_u,__LINE__) + end if + + ! Calculate global diagnostics for binfl + call output_diagnostics_continuous(mesh_i, mesh_o, data_i, binfl_o, & + "VIC b parameter", "unitless", ndiag=ndiag, rc=rc, mask_i=mask_i, frac_o=frac_o) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! ----------------------------------------------------------------- + ! Determine Ws + ! ----------------------------------------------------------------- + + ! Read in Ws into data_i + call mkpio_get_rawdata(pioid_i, 'Ws', mesh_i, data_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After mkpio_getrawdata in "//trim(subname)) + + ! Regrid Ws_i to Ws_o and check validity of output data + call regrid_rawdata(mesh_i, mesh_o, routehandle, data_i, ws_o, rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + do no = 1,ns_o + if (frac_o(no) == 0._r8) then + ws_o(no) = 0.75_r8 + end if + end do + if (min_bad(ws_o, min_valid_ws, 'Ws')) then + call shr_sys_abort() + end if + + ! Calculate global diagnostics for Ws + call output_diagnostics_continuous(mesh_i, mesh_o, data_i, ws_o, & + "VIC Ws parameter", "unitless", ndiag=ndiag, rc=rc, mask_i=mask_i, frac_o=frac_o) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! ----------------------------------------------------------------- + ! Determine DsMax + ! ----------------------------------------------------------------- + + ! Read in Dsmax into data_i + call mkpio_get_rawdata(pioid_i, 'Dsmax', mesh_i, data_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After mkpio_getrawdata in "//trim(subname)) + + ! Regrid Dsmax_i to Dsmax_o and check validity of output data + call regrid_rawdata(mesh_i, mesh_o, routehandle, data_i, dsmax_o, rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + do no = 1,ns_o + if (frac_o(no) == 0._r8) then + dsmax_o(no) = 10._r8 + end if + end do + if (min_bad(dsmax_o, min_valid_dsmax, 'Dsmax')) then + call shr_sys_abort() + end if + + ! Calculate global diagnostics for Dsmax + call output_diagnostics_continuous(mesh_i, mesh_o, data_i, dsmax_o, & + "VIC Dsmax parameter", "mm/day", ndiag=ndiag, rc=rc, mask_i=mask_i, frac_o=frac_o) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! ----------------------------------------------------------------- + ! Regrid Ds + ! ----------------------------------------------------------------- + + ! Read in Ds into data_i + call mkpio_get_rawdata(pioid_i, 'Ds', mesh_i, data_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After mkpio_getrawdata in "//trim(subname)) + + ! Regrid Ds_i to Ds_o and check validity of output data + call regrid_rawdata(mesh_i, mesh_o, routehandle, data_i, ds_o, rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + do no = 1,ns_o + if (frac_o(no) == 0._r8) then + ds_o(no) = 0.1_r8 + end if + end do + if (min_bad(ds_o, min_valid_ds, 'Ds')) then + call shr_sys_abort() + end if + + ! Calculate global diagnostics for Ws + call output_diagnostics_continuous(mesh_i, mesh_o, data_i, ds_o, & + "VIC Ds parameter", "unitless", ndiag=ndiag, rc=rc, mask_i=mask_i, frac_o=frac_o) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! ----------------------------------------------------------------- + ! Write output + ! ----------------------------------------------------------------- + + if (root_task) write(ndiag, '(a)') trim(subname)//" writing out VIC parameters" + call mkfile_output(pioid_o, mesh_o, 'binfl', binfl_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkfile_output for binfl') + call mkfile_output(pioid_o, mesh_o, 'Ws', ws_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkfile_output for Ws') + call mkfile_output(pioid_o, mesh_o, 'Dsmax', dsmax_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkfile_output for Dsmax') + call mkfile_output(pioid_o, mesh_o, 'Ds', ds_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkfile_output for Ds') + call pio_syncfile(pioid_o) + + ! ----------------------------------------------------------------- + ! Wrap up + ! ----------------------------------------------------------------- + + ! Close the input file + call pio_closefile(pioid_i) + call ESMF_VMLogMemInfo("After pio_closefile in "//trim(subname)) + + ! Release memory + call ESMF_RouteHandleDestroy(routehandle, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + call ESMF_MeshDestroy(mesh_i, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + call ESMF_VMLogMemInfo("After destroy operations in "//trim(subname)) + + if (root_task) then + write (ndiag,'(a)') 'Successfully made VIC parameters' + end if + + end subroutine mkVICparams + +end module mkVICparamsMod diff --git a/tools/mksurfdata_esmf/src/mkagfirepkmonthMod.F90 b/tools/mksurfdata_esmf/src/mkagfirepkmonthMod.F90 new file mode 100644 index 0000000000..6115e813f9 --- /dev/null +++ b/tools/mksurfdata_esmf/src/mkagfirepkmonthMod.F90 @@ -0,0 +1,249 @@ +module mkagfirepkmonthMod + + !----------------------------------------------------------------------- + ! Make agricultural fire peak month data + !----------------------------------------------------------------------- + + use ESMF + use pio , only : file_desc_t, pio_openfile, pio_closefile, pio_nowrite, pio_syncfile + use shr_kind_mod , only : r8 => shr_kind_r8, r4=>shr_kind_r4 + use shr_sys_mod , only : shr_sys_abort + use mkpioMod , only : mkpio_get_rawdata, pio_iotype, pio_iosystem + use mkvarctl , only : ndiag, root_task + use mkchecksMod , only : min_bad, max_bad + use mkdiagnosticsMod , only : output_diagnostics_index + use mkutilsMod , only : chkerr + use mkfileMod , only : mkfile_output + + implicit none + private ! By default make data private + + public :: mkagfirepkmon ! Set agricultural fire peak month + + integer , parameter :: min_valid = 1 + integer , parameter :: max_valid = 12 + integer , parameter :: unsetmon = 13 + + type(ESMF_DynamicMask) :: dynamicMask + + character(len=*) , parameter :: u_FILE_u = & + __FILE__ + +!=============================================================== +contains +!=============================================================== + + subroutine mkagfirepkmon(file_mesh_i, file_data_i, mesh_o, pioid_o, rc) + ! + ! Make agricultural fire peak month data from higher resolution data + ! + ! input/output variables + character(len=*) , intent(in) :: file_mesh_i ! input mesh file name + character(len=*) , intent(in) :: file_data_i ! input data file name + type(ESMF_Mesh) , intent(in) :: mesh_o ! output mesh + type(file_desc_t) , intent(inout) :: pioid_o + integer , intent(out) :: rc + ! + ! local variables: + type(ESMF_RouteHandle) :: routehandle + type(ESMF_Mesh) :: mesh_i + type(ESMF_Field) :: field_i + type(ESMF_Field) :: field_o + type(ESMF_Field) :: field_dstfrac + type(file_desc_t) :: pioid_i + integer :: k + integer :: ni,no + integer :: ns_i, ns_o + integer , allocatable :: mask_i(:) + real(r4), allocatable :: rmask_i(:) + real(r8), allocatable :: frac_o(:) + integer , allocatable :: idata_i(:) ! input grid: agricultural fire peak month + integer , allocatable :: agfirepkmon_o(:) ! agricultural fire peak month + real(r4), pointer :: dataptr(:) + real(r8), pointer :: dataptr_r8(:) + integer :: rcode, ier ! error status + integer :: srcTermProcessing_Value = 0 + character(len=*), parameter :: subname = 'mkagfirepkmon' + !----------------------------------------------------------------------- + + if (root_task) then + write(ndiag,*) + write(ndiag,'(1x,80a1)') ('=',k=1,80) + write(ndiag,*) + write(ndiag,'(a)') 'Attempting to make agricultural fire peak month data .....' + write(ndiag,'(a)') ' Input file is '//trim(file_data_i) + write(ndiag,'(a)') ' Input mesh file is '//trim(file_mesh_i) + end if + + ! Open input data file + rcode = pio_openfile(pio_iosystem, pioid_i, pio_iotype, trim(file_data_i), pio_nowrite) + call ESMF_VMLogMemInfo("After pio_openfile "//trim(file_data_i)) + + ! Read in input mesh + mesh_i = ESMF_MeshCreate(filename=trim(file_mesh_i), fileformat=ESMF_FILEFORMAT_ESMFMESH, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After create mesh_i in "//trim(subname)) + + ! Determine ns_i + call ESMF_MeshGet(mesh_i, numOwnedElements=ns_i, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Determine ns_o and allocate output data + call ESMF_MeshGet(mesh_o, numOwnedElements=ns_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + allocate (agfirepkmon_o(ns_o)); agfirepkmon_o(:) = -999 + + ! Get the landmask from the file and reset the mesh mask based on that + allocate(rmask_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort(subname//" ERROR in allocating rmask_i") + allocate(mask_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort(subname//" ERROR in allocating mask_i") + call mkpio_get_rawdata(pioid_i, 'LANDMASK', mesh_i, rmask_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + do ni = 1,ns_i + if (rmask_i(ni) > 0.) then + mask_i(ni) = 1 + else + mask_i(ni) = 0 + end if + end do + call ESMF_MeshSet(mesh_i, elementMask=mask_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! Read in agfirepkmon_i + allocate(idata_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort(subname//" error in allocating idata_i") + call mkpio_get_rawdata(pioid_i, 'abm', mesh_i, idata_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After mkpio_getrawdata in "//trim(subname)) + + ! Create ESMF fields that will be used below + field_i = ESMF_FieldCreate(mesh_i, ESMF_TYPEKIND_R4, meshloc=ESMF_MESHLOC_ELEMENT, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + field_o = ESMF_FieldCreate(mesh_o, ESMF_TYPEKIND_R4, meshloc=ESMF_MESHLOC_ELEMENT, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + field_dstfrac = ESMF_FieldCreate(mesh_o, ESMF_TYPEKIND_R8, meshloc=ESMF_MESHLOC_ELEMENT, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! Create a route handle + call ESMF_FieldRegridStore(field_i, field_o, routehandle=routehandle, & + regridmethod=ESMF_REGRIDMETHOD_CONSERVE, srcTermProcessing=srcTermProcessing_Value, & + ignoreDegenerate=.true., unmappedaction=ESMF_UNMAPPEDACTION_IGNORE, & + dstFracField= field_dstfrac, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After regridstore in "//trim(subname)) + + ! Determine frac_o + call ESMF_FieldGet(field_dstfrac, farrayptr=dataptr_r8, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + allocate(frac_o(ns_o)) + frac_o(:) = dataptr_r8(:) + + ! Create a dynamic mask object + ! The dynamic mask object further holds a pointer to the routine that will be called in order to + ! handle dynamically masked elements - in this case its DynMaskProc (see below) + call ESMF_DynamicMaskSetR4R8R4(dynamicMask, dynamicMaskRoutine=get_dominant_indices, & + handleAllElements=.true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! Determine dominant fire month + ! **NOTE** the use of the dynamicMask argument to the ESMF_FieldRegrid call + call ESMF_FieldGet(field_i, farrayptr=dataptr, rc=rc) + dataptr(:) = real(idata_i(:), kind=r4) + call ESMF_FieldGet(field_o, farrayptr=dataptr, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + dataptr(:) = 0._r4 + call ESMF_FieldRegrid(field_i, field_o, routehandle=routehandle, dynamicMask=dynamicMask, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_FieldGet(field_o, farrayptr=dataptr, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + do no = 1,ns_o + agfirepkmon_o(no) = int(dataptr(no)) + end do + + ! Check validity of output data + if (min_bad(agfirepkmon_o, min_valid, 'agfirepkmon') .or. & + max_bad(agfirepkmon_o, unsetmon , 'agfirepkmon')) then + call shr_sys_abort() + end if + + ! Close the file + call pio_closefile(pioid_i) + + ! Write out data + if (root_task) write(ndiag, '(a)') trim(subname)//" writing abm (agricultural fire peak month)" + call mkfile_output(pioid_o, mesh_o, 'abm', agfirepkmon_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkfile_output') + call pio_syncfile(pioid_o) + + ! Output diagnostics comparing global area of each peak month on input and output grids + call output_diagnostics_index(mesh_i, mesh_o, mask_i, frac_o, & + 1, 13, idata_i, agfirepkmon_o, 'peak fire month', ndiag, rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + + ! Release memory + call ESMF_RouteHandleDestroy(routehandle, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + call ESMF_MeshDestroy(mesh_i, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + call ESMF_FieldDestroy(field_i, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + call ESMF_FieldDestroy(field_o, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + call ESMF_FieldDestroy(field_dstfrac, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + call ESMF_VMLogMemInfo("After destroy operations in "//trim(subname)) + + if (root_task) then + write (ndiag,'(a)') 'Successfully made Agricultural fire peak month' + write (ndiag,*) + end if + + end subroutine mkagfirepkmon + + !================================================================================================ + subroutine get_dominant_indices(dynamicMaskList, dynamicSrcMaskValue, dynamicDstMaskValue, rc) + + ! input/output arguments + type(ESMF_DynamicMaskElementR4R8R4) , pointer :: dynamicMaskList(:) + real(ESMF_KIND_R4) , intent(in), optional :: dynamicSrcMaskValue + real(ESMF_KIND_R4) , intent(in), optional :: dynamicDstMaskValue + integer , intent(out) :: rc + + ! local variables + integer :: ni, no, n + real(ESMF_KIND_R4) :: wts_o(min_valid:max_valid) + integer :: maxindex(1) + logical :: hasdata + !--------------------------------------------------------------- + + rc = ESMF_SUCCESS + + if (associated(dynamicMaskList)) then + do no = 1, size(dynamicMaskList) + hasdata = .false. + wts_o(:) = 0.d0 + do ni = 1, size(dynamicMaskList(no)%factor) + if (dynamicMaskList(no)%srcElement(ni) > 0.d0) then + do n = min_valid,max_valid + if ( dynamicMaskList(no)%srcElement(ni) == n) then + wts_o(n) = wts_o(n) + dynamicMaskList(no)%factor(ni) + hasdata = .true. + end if + enddo + end if + end do + + ! Determine the most dominant index of wts_o + if (hasdata) then + maxindex = maxloc(wts_o(:)) + dynamicMaskList(no)%dstElement = real(maxindex(1), kind=r4) + else + dynamicMaskList(no)%dstElement = real(unsetmon, kind=r4) + end if + end do + end if + + end subroutine get_dominant_indices + +end module mkagfirepkmonthMod diff --git a/tools/mksurfdata_esmf/src/mkchecksMod.F90 b/tools/mksurfdata_esmf/src/mkchecksMod.F90 new file mode 100644 index 0000000000..f583463ab0 --- /dev/null +++ b/tools/mksurfdata_esmf/src/mkchecksMod.F90 @@ -0,0 +1,218 @@ +module mkchecksMod + + !----------------------------------------------------------------------- + ! Generic routines to check validity of output fields + !----------------------------------------------------------------------- + + use shr_kind_mod, only : r8 => shr_kind_r8, r4 => shr_kind_r4 + + implicit none + private + + public :: min_bad ! check the minimum value of a field + public :: max_bad ! check the maximum value of a field + + interface min_bad + module procedure min_bad_int + module procedure min_bad_r8 + module procedure min_bad_r4 + end interface min_bad + + interface max_bad + module procedure max_bad_int + module procedure max_bad_r8 + module procedure max_bad_r4 + end interface max_bad + +!=============================================================== +contains +!=============================================================== + + logical function min_bad_r8(data, min_allowed, varname) + + ! Confirm that no value of data is less than min_allowed. + ! Returns true if errors found, false otherwise. + ! Also prints offending points + + ! !ARGUMENTS: + real(r8) , intent(in) :: data(:) ! array of data to check + real(r8) , intent(in) :: min_allowed ! minimum valid value + character(len=*) , intent(in) :: varname ! name of field + + ! !LOCAL VARIABLES: + logical :: errors_found ! true if any errors have been found + integer :: n ! index + character(len=*), parameter :: subname = 'min_bad_r8' + !------------------------------------------------------------------------------ + + errors_found = .false. + + do n = 1, size(data) + if (data(n) < min_allowed) then + write(6,*) subname//' ERROR: ', trim(varname), ' = ', data(n), ' less than ',& + min_allowed, ' at ', n + errors_found = .true. + end if + end do + + min_bad_r8 = errors_found + end function min_bad_r8 + + !=============================================================== + logical function min_bad_r4(data, min_allowed, varname) + + ! Confirm that no value of data is less than min_allowed. + ! Returns true if errors found, false otherwise. + ! Also prints offending points + + ! !ARGUMENTS: + real(r4) , intent(in) :: data(:) ! array of data to check + real(r4) , intent(in) :: min_allowed ! minimum valid value + character(len=*) , intent(in) :: varname ! name of field + + ! !LOCAL VARIABLES: + logical :: errors_found ! true if any errors have been found + integer :: n ! index + character(len=*), parameter :: subname = 'min_bad_r8' + !------------------------------------------------------------------------------ + + errors_found = .false. + + do n = 1, size(data) + if (data(n) < min_allowed) then + write(6,*) subname//' ERROR: ', trim(varname), ' = ', data(n), ' less than ',& + min_allowed, ' at ', n + errors_found = .true. + end if + end do + + min_bad_r4 = errors_found + end function min_bad_r4 + + !=============================================================== + logical function min_bad_int(data, min_allowed, varname) + + ! !DESCRIPTION: + ! Confirm that no value of data is less than min_allowed. + ! Returns true if errors found, false otherwise. + ! Also prints offending points + + ! !ARGUMENTS: + integer , intent(in) :: data(:) ! array of data to check + integer , intent(in) :: min_allowed ! minimum valid value + character(len=*) , intent(in) :: varname ! name of field + + ! !LOCAL VARIABLES: + logical :: errors_found ! true if any errors have been found + integer :: n ! index + character(len=*), parameter :: subname = 'min_bad_int' + !------------------------------------------------------------------------------ + + errors_found = .false. + + do n = 1, size(data) + if (data(n) < min_allowed) then + write(6,*) subname//' ERROR: ', trim(varname), ' = ', data(n), ' less than ',& + min_allowed, ' at ', n + errors_found = .true. + end if + end do + + min_bad_int = errors_found + end function min_bad_int + + !=============================================================== + logical function max_bad_r8(data, max_allowed, varname) + + ! Confirm that no value of data is greate than max_allowed. + ! Returns true if errors found, false otherwise. + ! Also prints offending points + + ! !ARGUMENTS: + real(r8) , intent(in) :: data(:) ! array of data to check + real(r8) , intent(in) :: max_allowed ! maximum valid value + character(len=*) , intent(in) :: varname ! name of field + + ! !LOCAL VARIABLES: + logical :: errors_found ! true if any errors have been found + integer :: n ! index + character(len=*), parameter :: subname = 'max_bad_r8' + !------------------------------------------------------------------------------ + + errors_found = .false. + + do n = 1, size(data) + if (data(n) > max_allowed) then + write(6,*) subname//' ERROR: ', trim(varname), ' = ', data(n), ' greater than ',& + max_allowed, ' at ', n + errors_found = .true. + end if + end do + + max_bad_r8 = errors_found + end function max_bad_r8 + + !=============================================================== + logical function max_bad_r4(data, max_allowed, varname) + + ! Confirm that no value of data is greate than max_allowed. + ! Returns true if errors found, false otherwise. + ! Also prints offending points + + ! !ARGUMENTS: + real(r4) , intent(in) :: data(:) ! array of data to check + real(r4) , intent(in) :: max_allowed ! maximum valid value + character(len=*) , intent(in) :: varname ! name of field + + ! !LOCAL VARIABLES: + logical :: errors_found ! true if any errors have been found + integer :: n ! index + character(len=*), parameter :: subname = 'max_bad_r8' + !------------------------------------------------------------------------------ + + errors_found = .false. + + do n = 1, size(data) + if (data(n) > max_allowed) then + write(6,*) subname//' ERROR: ', trim(varname), ' = ', data(n), ' greater than ',& + max_allowed, ' at ', n + errors_found = .true. + end if + end do + + max_bad_r4 = errors_found + end function max_bad_r4 + + !=============================================================== + logical function max_bad_int(data, max_allowed, varname) + + ! !DESCRIPTION: + ! Confirm that no value of data is greate than max_allowed. + ! Returns true if errors found, false otherwise. + ! Also prints offending points + + ! !ARGUMENTS: + integer , intent(in) :: data(:) ! array of data to check + integer , intent(in) :: max_allowed ! maximum valid value + character(len=*) , intent(in) :: varname ! name of field + + ! !LOCAL VARIABLES: + logical :: errors_found ! true if any errors have been found + integer :: n ! index + character(len=*), parameter :: subname = 'max_bad_int' + !------------------------------------------------------------------------------ + + errors_found = .false. + + do n = 1, size(data) + if (data(n) > max_allowed) then + write(6,*) subname//' ERROR: ', trim(varname), ' = ', data(n), ' greater than ',& + max_allowed, ' at ', n + errors_found = .true. + end if + end do + + max_bad_int = errors_found + end function max_bad_int + +end module mkchecksMod diff --git a/tools/mksurfdata_esmf/src/mkdiagnosticsMod.F90 b/tools/mksurfdata_esmf/src/mkdiagnosticsMod.F90 new file mode 100644 index 0000000000..8b8730f83b --- /dev/null +++ b/tools/mksurfdata_esmf/src/mkdiagnosticsMod.F90 @@ -0,0 +1,451 @@ +module mkdiagnosticsMod + + !----------------------------------------------------------------------- + ! Output diagnostics to log file + !----------------------------------------------------------------------- + + use ESMF + use shr_kind_mod , only : r8 => shr_kind_r8 + use shr_sys_mod , only : shr_sys_abort + use mkutilsMod , only : chkerr + use mkesmfMod , only : get_meshareas + use mkvarctl , only : mpicom, root_task + + implicit none + private + +#include + + public :: output_diagnostics_area ! output diagnostics for field that is % of grid area + public :: output_diagnostics_continuous ! output diagnostics for a continuous (real-valued) field + public :: output_diagnostics_continuous_outonly ! output diagnostics for a continuous (real-valued) field + ! just on the output grid + public :: output_diagnostics_index ! output diagnostics for an index field + + character(len=*) , parameter :: u_FILE_u = & + __FILE__ + +!=============================================================== +contains +!=============================================================== + + subroutine output_diagnostics_area(mesh_i, mesh_o, mask_i, frac_o, & + data_i, data_o, name, percent, ndiag, rc) + + ! Output diagnostics for a field that gives either fraction or percent of grid cell area + + ! input/output variables + type(ESMF_Mesh) , intent(in) :: mesh_i + type(ESMF_Mesh) , intent(in) :: mesh_o + integer , intent(in) :: mask_i(:) + real(r8) , intent(in) :: frac_o(:) ! land fraction output grid + real(r8) , intent(in) :: data_i(:) ! data on input grid + real(r8) , intent(in) :: data_o(:) ! data on output grid + character(len=*) , intent(in) :: name ! name of field + logical , intent(in) :: percent ! is field specified as percent? (alternative is fraction) + integer , intent(in) :: ndiag + integer , intent(out) :: rc + + ! local variables: + integer :: ns_i, ns_o ! sizes of input & output grids + integer :: ni,no,k ! indices + real(r8) :: loc_gdata_i ! local_global sum of input data + real(r8) :: loc_gdata_o ! local_global sum of output data + real(r8) :: gdata_i ! global sum of input data + real(r8) :: gdata_o ! global sum of output data + real(r8) :: loc_garea_i ! local global sum of input area + real(r8) :: loc_garea_o ! local global sum of output area + real(r8) :: garea_i ! global sum of input area + real(r8) :: garea_o ! global sum of output area + integer :: ier ! error code + real(r8), allocatable :: area_i(:) + real(r8), allocatable :: area_o(:) + character(len=*), parameter :: subname = "output_diagnostics_area" + !------------------------------------------------------------------------------ + + rc = ESMF_SUCCESS + + ! Determine ns_i and ns_o + call ESMF_MeshGet(mesh_i, numOwnedElements=ns_i, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_MeshGet(mesh_o, numOwnedElements=ns_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Determine areas + allocate(area_i(ns_i)) + allocate(area_o(ns_o)) + call get_meshareas(mesh_i, area_i, rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call get_meshareas(mesh_o, area_o, rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! Error check for array size consistencies + if (size(mask_i) /= ns_i) then + write(6,*) subname//' ERROR: incorrect size of mask_i' + write(6,*) 'size(mask_i) = ', size(mask_i) + write(6,*) 'ns_i = ', ns_i + call shr_sys_abort() + end if + if (size(frac_o) /= ns_o) then + write(6,*) subname//' ERROR: incorrect size of frac_o' + write(6,*) 'size(frac_o) = ', size(frac_o) + write(6,*) 'ns_o = ', ns_o + call shr_sys_abort() + end if + + ! Sums on input grid + loc_gdata_i = 0. + loc_garea_i = 0. + do ni = 1,ns_i + loc_garea_i = loc_garea_i + area_i(ni) + loc_gdata_i = loc_gdata_i + data_i(ni) * area_i(ni) * mask_i(ni) + end do + call mpi_reduce(loc_gdata_i,gdata_i,1,MPI_REAL8,MPI_SUM,0,mpicom,ier) + call mpi_reduce(loc_garea_i,garea_i,1,MPI_REAL8,MPI_SUM,0,mpicom,ier) + + ! Sums on output grid + loc_gdata_o = 0. + loc_garea_o = 0. + do no = 1,ns_o + loc_garea_o = loc_garea_o + area_o(no) + loc_gdata_o = loc_gdata_o + data_o(no) * area_o(no) * frac_o(no) + end do + call mpi_reduce(loc_gdata_o,gdata_o,1,MPI_REAL8,MPI_SUM,0,mpicom,ier) + call mpi_reduce(loc_garea_o,garea_o,1,MPI_REAL8,MPI_SUM,0,mpicom,ier) + + ! Correct units + if (percent) then + gdata_i = gdata_i / 100._r8 + gdata_o = gdata_o / 100._r8 + end if + + ! Diagnostic output + if (root_task) then + write(ndiag,*) + write(ndiag,*) + write(ndiag,'(1x,70a1)') ('.',k=1,70) + write(ndiag,'(a)') ' diagnostics for '//trim(name) + write (ndiag,201) +201 format (1x,'surface type input grid area output grid area'/ & + 1x,' 10**6 km**2 10**6 km**2 ') + write (ndiag,'(1x,70a1)') ('.',k=1,70) + write (ndiag,*) + write (ndiag,202) name, gdata_i*1.e-06, gdata_o*1.e-06 + write (ndiag,202) 'all surface', garea_i*1.e-06, garea_o*1.e-06 +202 format (1x,a12, f14.3,f17.3) + end if + + end subroutine output_diagnostics_area + + !=============================================================== + subroutine output_diagnostics_continuous(mesh_i, mesh_o, data_i, data_o, & + name, units, ndiag, rc, mask_i, frac_o, nomask) + + ! Output diagnostics for a continuous field (but not area, for + ! which there is a different routine) + + ! input/output variables + type(ESMF_Mesh) , intent(in) :: mesh_i + type(ESMF_Mesh) , intent(in) :: mesh_o + real(r8) , intent(in) :: data_i(:) ! data on input grid + real(r8) , intent(in) :: data_o(:) ! data on output grid + character(len=*) , intent(in) :: name ! name of field + character(len=*) , intent(in) :: units ! units of field + integer , intent(in) :: ndiag + logical, optional, intent(in) :: nomask + integer, optional, intent(in) :: mask_i(:) + real(r8),optional, intent(in) :: frac_o(:) + integer , intent(out) :: rc + + ! local variables + real(r8), allocatable :: area_i(:) + real(r8), allocatable :: area_o(:) + real(r8) :: loc_gdata_i ! local sum of input data + real(r8) :: loc_gdata_o ! local sum of output data + real(r8) :: gdata_i ! global sum of input data + real(r8) :: gdata_o ! global sum of output data + real(r8) :: loc_gwt_i ! local global sum of input weights (area * frac) + real(r8) :: loc_gwt_o ! local global sum of output weights (area * frac) + real(r8) :: gwt_i ! global sum of input weights (area * frac) + real(r8) :: gwt_o ! global sum of output weights (area * frac) + integer :: ns_i, ns_o ! sizes of input & output grids + integer :: ni,no,k ! indices + integer :: ier ! error code + logical :: lnomask + character(len=*), parameter :: subname = "output_diagnostics_continuous" + !------------------------------------------------------------------------------ + + rc = ESMF_SUCCESS + + lnomask = .false. + if (present(nomask)) then + lnomask = nomask + else if (.not. (present(mask_i) .and. present(frac_o))) then + write(6,*) 'Must pass argument nomask if not passing mask_i and frac_o.' + call shr_sys_abort() + end if + + ! Determine ns_i and ns_o + call ESMF_MeshGet(mesh_i, numOwnedElements=ns_i, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_MeshGet(mesh_o, numOwnedElements=ns_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Determine areas + allocate(area_i(ns_i)) + allocate(area_o(ns_o)) + call get_meshareas(mesh_i, area_i, rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call get_meshareas(mesh_o, area_o, rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! Error check for array size consistencies + if (size(data_i) /= ns_i .or. size(data_o) /= ns_o) then + write(6,*) subname//' ERROR: array size inconsistencies for ', trim(name) + write(6,*) 'size(data_i) = ', size(data_i) + write(6,*) 'ns_i = ', ns_i + write(6,*) 'size(data_o) = ', size(data_o) + write(6,*) 'ns_o = ', ns_o + call shr_sys_abort() + end if + if (present(mask_i) .and. present(frac_o)) then + if (size(frac_o) /= ns_o) then + write(6,*) subname//' ERROR: incorrect size of frac_o' + write(6,*) 'size(frac_o) = ', size(frac_o) + write(6,*) 'ns_o = ', ns_o + call shr_sys_abort() + end if + if (size(mask_i) /= ns_i) then + write(6,*) subname//' ERROR: incorrect size of mask_i' + write(6,*) 'size(mask_i) = ', size(mask_i) + write(6,*) 'ns_i = ', ns_i + call shr_sys_abort() + end if + end if + + ! Sums on input grid + loc_gdata_i = 0. + loc_gwt_i = 0. + do ni = 1,ns_i + if (lnomask) then + loc_gdata_i = loc_gdata_i + data_i(ni) * area_i(ni) + loc_gwt_i = loc_gwt_i + area_i(ni) + else + loc_gdata_i = loc_gdata_i + data_i(ni) * area_i(ni) * mask_i(ni) + loc_gwt_i = loc_gwt_i + area_i(ni) * mask_i(ni) + end if + end do + call mpi_reduce(loc_gdata_i, gdata_i, 1, MPI_REAL8, MPI_SUM, 0, mpicom, ier) + call mpi_reduce(loc_gwt_i , gwt_i , 1, MPI_REAL8, MPI_SUM, 0, mpicom, ier) + + ! Sums on output grid + loc_gdata_o = 0. + loc_gwt_o = 0. + do no = 1,ns_o + if (lnomask) then + loc_gdata_o = loc_gdata_o + data_o(no) * area_o(no) + loc_gwt_o = loc_gwt_o + area_o(no) + else + loc_gdata_o = loc_gdata_o + data_o(no) * area_o(no) * frac_o(no) + loc_gwt_o = loc_gwt_o + area_o(no) * frac_o(no) + end if + end do + call mpi_reduce(loc_gdata_o, gdata_o, 1, MPI_REAL8, MPI_SUM, 0, mpicom, ier) + call mpi_reduce(loc_gwt_o , gwt_o , 1, MPI_REAL8, MPI_SUM, 0, mpicom, ier) + + ! Correct units + gdata_i = gdata_i / gwt_i + gdata_o = gdata_o / gwt_o + + ! Diagnostic output + if (root_task) then + write (ndiag,*) + write (ndiag,'(1x,70a1)') ('.',k=1,70) + write (ndiag,'(1x,a)')'output diagnostics for '//trim(name)//' with units = '//trim(units) + write (ndiag,'(1x,a,f17.3,a,f17.3)')' global input sum= ',gdata_i,' global output sum',gdata_o + write (ndiag,'(1x,70a1)') ('.',k=1,70) + write (ndiag,*) + end if + + end subroutine output_diagnostics_continuous + + !=============================================================== + subroutine output_diagnostics_continuous_outonly(mesh_o, frac_o, data_o, name, units, ndiag, rc) + ! + ! Output diagnostics for a continuous field, just on the output grid + ! This is used when the average of the field on the input grid is not of interest (e.g., + ! when the output quantity is the standard deviation of the input field) + ! + ! input/output variables + type(ESMF_Mesh) , intent(in) :: mesh_o + real(r8) , intent(in) :: frac_o(:) + real(r8) , intent(in) :: data_o(:) ! data on output grid + character(len=*) , intent(in) :: name ! name of field + character(len=*) , intent(in) :: units ! units of field + integer , intent(in) :: ndiag ! unit number for diagnostic output + integer , intent(out) :: rc + + ! local variables: + real(r8), allocatable :: area_o(:) + real(r8) :: gdata_o ! global sum of output data + real(r8) :: gwt_o ! global sum of output weights (area * frac) + integer :: ns_o ! size of output grid + integer :: no,k ! indices + character(len=*), parameter :: subname = "output_diagnostics_continuous_outonly" + !------------------------------------------------------------------------------ + + rc = ESMF_SUCCESS + + ! Determine ns_o + call ESMF_MeshGet(mesh_o, numOwnedElements=ns_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Determine area_o + allocate(area_o(ns_o)) + call get_meshareas(mesh_o, area_o, rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! Error check for array size consistencies + if (size(data_o) /= ns_o) then + write(6,*) subname//' ERROR: array size inconsistencies for ', trim(name) + write(6,*) 'size(data_o) = ', size(data_o) + write(6,*) 'ns_o = ', ns_o + call shr_sys_abort() + end if + + ! Sums on output grid + gdata_o = 0. + gwt_o = 0. + do no = 1,ns_o + gdata_o = gdata_o + data_o(no)*area_o(no)*frac_o(no) + gwt_o = gwt_o + area_o(no)*frac_o(no) + end do + + ! Correct units + gdata_o = gdata_o / gwt_o + + ! Diagnostic output + if (root_task) then + write (ndiag,*) + write (ndiag,'(1x,70a1)') ('.',k=1,70) + write (ndiag,2001) + write (ndiag,2002) units +2001 format (1x,' parameter output grid') +2002 format (1x,' ', a24) + write (ndiag,'(1x,70a1)') ('.',k=1,70) + write (ndiag,*) + write (ndiag,2003) name, gdata_o +2003 format (1x,a12, f22.3) + end if + + end subroutine output_diagnostics_continuous_outonly + + !=============================================================== + subroutine output_diagnostics_index(mesh_i, mesh_o, mask_i, frac_o, & + min_valid, max_valid, data_i, data_o, name, ndiag, rc) + ! + ! Output diagnostics for an index field: area of each index in input and output + ! + ! input/output variables + type(ESMF_Mesh) , intent(in) :: mesh_i + type(ESMF_Mesh) , intent(in) :: mesh_o + integer , intent(in) :: mask_i(:) + real(r8) , intent(in) :: frac_o(:) + integer , intent(in) :: min_valid + integer , intent(in) :: max_valid + integer , intent(in) :: data_i(:) ! data on input grid + integer , intent(in) :: data_o(:) ! data on output grid + character(len=*) , intent(in) :: name ! name of field + integer , intent(in) :: ndiag ! unit number for diagnostic output + integer , intent(out) :: rc + + ! local variables: + integer :: ns_i, ns_o ! sizes of input & output grids + integer :: ni, no, k ! indices + real(r8), allocatable :: area_i(:) + real(r8), allocatable :: area_o(:) + real(r8), allocatable :: loc_garea_i(:) ! input grid: global area of each index + real(r8), allocatable :: loc_garea_o(:) ! output grid: global area of each index + real(r8), allocatable :: garea_i(:) ! input grid: global area of each index + real(r8), allocatable :: garea_o(:) ! output grid: global area of each index + integer :: ier ! error status + character(len=*), parameter :: subname = 'output_diagnostics_index' + !----------------------------------------------------------------------- + + rc = ESMF_SUCCESS + + ! Determine ns_i and ns_o + call ESMF_MeshGet(mesh_i, numOwnedElements=ns_i, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_MeshGet(mesh_o, numOwnedElements=ns_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Determine areas + allocate(area_i(ns_i)) + allocate(area_o(ns_o)) + call get_meshareas(mesh_i, area_i, rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call get_meshareas(mesh_o, area_o, rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! Error check for array size consistencies + if (size(data_i) /= ns_i .or. size(data_o) /= ns_o) then + write(6,*) subname//' ERROR: array size inconsistencies for ', trim(name) + write(6,*) 'size(data_i) = ', size(data_i) + write(6,*) 'ns_i = ', ns_i + write(6,*) 'size(data_o) = ', size(data_o) + write(6,*) 'ns_o = ', ns_o + !call shr_sys_abort(subname,file=__FILE__,line=__LINE__) + call shr_sys_abort() + end if + if (size(mask_i) /= ns_i) then + write(6,*) subname//' ERROR: incorrect size of mask_i' + write(6,*) 'size(mask_i) = ', size(mask_i) + write(6,*) 'ns_i = ', ns_i + call shr_sys_abort() + end if + + ! Sum areas on input grid + allocate(loc_garea_i(min_valid:max_valid), stat=ier) + if (ier/=0) call shr_sys_abort() + allocate(garea_i(min_valid:max_valid), stat=ier) + if (ier/=0) call shr_sys_abort() + loc_garea_i(:) = 0. + do ni = 1, ns_i + k = data_i(ni) + if (k >= min_valid .and. k <= max_valid) then + loc_garea_i(k) = loc_garea_i(k) + area_i(ni) * mask_i(ni) + end if + end do + call mpi_reduce(loc_garea_i, garea_i, size(garea_i), MPI_REAL8, MPI_SUM, 0, mpicom, ier) + + ! Sum areas on output grid + allocate(loc_garea_o(min_valid:max_valid), stat=ier) + if (ier/=0) call shr_sys_abort() + allocate(garea_o(min_valid:max_valid), stat=ier) + if (ier/=0) call shr_sys_abort() + loc_garea_o(:) = 0. + do no = 1, ns_o + k = data_o(no) + if (k >= min_valid .and. k <= max_valid) then + loc_garea_o(k) = loc_garea_o(k) + area_o(no) * frac_o(no) + end if + end do + call mpi_reduce(loc_garea_o, garea_o, size(garea_o), MPI_REAL8, MPI_SUM, 0, mpicom, ier) + + ! Write results + if (root_task) then + write (ndiag,*) + write (ndiag,'(1x,60a1)') ('.',k=1,60) + write (ndiag,2001) +2001 format (1x,'index input grid area output grid area',/ & + 1x,' 10**6 km**2 10**6 km**2') + write (ndiag,'(1x,60a1)') ('.',k=1,60) + do k = min_valid, max_valid + write (ndiag,'(1x,i9,f17.3,f18.3)') k, garea_i(k)*1.e-06, garea_o(k)*1.e-06 + end do + end if + + end subroutine output_diagnostics_index + +end module mkdiagnosticsMod diff --git a/tools/mksurfdata_esmf/src/mkdomainMod.F90 b/tools/mksurfdata_esmf/src/mkdomainMod.F90 new file mode 100644 index 0000000000..32c5854d4e --- /dev/null +++ b/tools/mksurfdata_esmf/src/mkdomainMod.F90 @@ -0,0 +1,71 @@ +module mkdomainMod + + !------------------------------- + ! Determine lon/lat of model + !------------------------------- + + use ESMF + use pio + use shr_kind_mod, only : r8 => shr_kind_r8 + use shr_sys_mod , only : shr_sys_abort + use mkutilsMod , only : chkerr + use mkvarctl , only : root_task, ndiag + use mkfileMod , only : mkfile_output + + implicit none + private + + public :: mkdomain + + character(len=*) , parameter :: u_FILE_u = & + __FILE__ + +!================================================================================= +contains +!================================================================================= + + subroutine mkdomain(mesh_o, lon_o, lat_o, rc) + + ! input output variables + type(ESMF_Mesh) , intent(in) :: mesh_o + real(r8) , intent(out) :: lon_o(:) + real(r8) , intent(out) :: lat_o(:) + integer , intent(out) :: rc + + ! local variables: + integer :: no + integer :: ns_o + integer :: spatialDim + integer :: k + real(r8), allocatable :: ownedElemCoords(:) + character(len=*), parameter :: subname = 'mkdomain' + !----------------------------------------------------------------------- + + rc = ESMF_SUCCESS + + if (root_task) then + write(ndiag,*) + write(ndiag,'(1x,80a1)') ('=',k=1,80) + write(ndiag,*) + write(ndiag,'(a)') 'Attempting to create model lats and lons from model mesh .....' + flush(ndiag) + end if + + call ESMF_MeshGet(mesh_o, spatialDim=spatialDim, numOwnedElements=ns_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + allocate(ownedElemCoords(spatialDim*ns_o)) + call ESMF_MeshGet(mesh_o, ownedElemCoords=ownedElemCoords, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + do no = 1,ns_o + lon_o(no) = ownedElemCoords(2*no-1) + lat_o(no) = ownedElemCoords(2*no) + end do + + if (root_task) then + write (ndiag,'(a)') 'Successfully made model lats and lons' + flush(ndiag) + end if + + end subroutine mkdomain + +end module mkdomainMod diff --git a/tools/mksurfdata_esmf/src/mkesmfMod.F90 b/tools/mksurfdata_esmf/src/mkesmfMod.F90 new file mode 100644 index 0000000000..893b1fec80 --- /dev/null +++ b/tools/mksurfdata_esmf/src/mkesmfMod.F90 @@ -0,0 +1,398 @@ +module mkesmfMod + + use ESMF + use shr_kind_mod , only : r8 => shr_kind_r8, r4 => shr_kind_r4 + use shr_sys_mod , only : shr_sys_abort + use mkUtilsMod , only : chkerr + + implicit none + private + + public :: regrid_rawdata + public :: get_meshareas + public :: create_routehandle_r4 + public :: create_routehandle_r8 + + interface regrid_rawdata + module procedure regrid_rawdata1d_r4 + module procedure regrid_rawdata1d_r8 + module procedure regrid_rawdata2d_r4 + module procedure regrid_rawdata2d_r8 + end interface regrid_rawdata + + character(len=*) , parameter :: u_FILE_u = & + __FILE__ + +!=============================================================== +contains +!=============================================================== + + subroutine create_routehandle_r4(mesh_i, mesh_o, norm_by_fracs, routehandle, frac_o, rc) + + ! input/output variables + type(ESMF_Mesh) , intent(in) :: mesh_i + type(ESMF_Mesh) , intent(in) :: mesh_o + ! If norm_by_fracs is .true., then remapping is done using ESMF_NORMTYPE_FRACAREA; + ! otherwise, remapping is done using ESMF_NORMTYPE_DSTAREA. FRACAREA normalization + ! adds a normalization factor of the fraction of the unmasked source grid that + ! overlaps with a destination cell. FRACAREA normalization is appropriate when you + ! want to treat values outside the mask as missing values that shouldn't contribute + ! to the average (this is appropriate for most fields); DSTAREA normalization is + ! appropriate when you want to treat values outside the mask as 0 (this is + ! appropriate for PCT cover fields where we want the final value to be expressed as + ! percent of the entire gridcell area). + logical , intent(in) :: norm_by_fracs + type(ESMF_RouteHandle) , intent(inout) :: routehandle + real(r4), optional , intent(inout) :: frac_o(:) + integer , intent(out) :: rc + + ! local variables + integer :: srcMaskValue = 0 ! ignore source points where the mesh mask is 0 + integer :: dstMaskValue = -987987 ! don't ingore any destination points + integer :: srcTermProcessing_Value = 0 + type(ESMF_NormType_Flag) :: normtype + type(ESMF_Field) :: field_i + type(ESMF_Field) :: field_o + type(ESMF_Field) :: dstfracfield + real(r8), pointer :: dataptr(:) + character(len=*), parameter :: subname = 'create_routehandle_r4' + ! -------------------------------------------- + + rc = ESMF_SUCCESS + + field_i = ESMF_FieldCreate(mesh_i, ESMF_TYPEKIND_R4, meshloc=ESMF_MESHLOC_ELEMENT, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + field_o = ESMF_FieldCreate(mesh_o, ESMF_TYPEKIND_R4, meshloc=ESMF_MESHLOC_ELEMENT, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + dstfracfield = ESMF_FieldCreate(mesh_o, ESMF_TYPEKIND_R8, meshloc=ESMF_MESHLOC_ELEMENT, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + if (norm_by_fracs) then + normtype = ESMF_NORMTYPE_FRACAREA + else + normtype = ESMF_NORMTYPE_DSTAREA + end if + + ! Create route handle to map field_model to field_data + call ESMF_FieldRegridStore(field_i, field_o, routehandle=routehandle, & + regridmethod=ESMF_REGRIDMETHOD_CONSERVE, normType=normtype, & + srcMaskValues=(/srcMaskValue/), & + dstMaskValues=(/dstMaskValue/), & + srcTermProcessing=srcTermProcessing_Value, & + ignoreDegenerate=.true., unmappedaction=ESMF_UNMAPPEDACTION_IGNORE, & + dstFracField= dstFracField, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After regridstore in "//trim(subname)) + + call ESMF_FieldGet(dstfracfield, farrayptr=dataptr, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + if (present(frac_o)) then + frac_o(:) = real(dataptr(:), kind=r4) + end if + + call ESMF_FieldDestroy(field_i, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + call ESMF_FieldDestroy(field_o, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + call ESMF_FieldDestroy(dstfracfield, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + + end subroutine create_routehandle_r4 + + !=============================================================== + subroutine create_routehandle_r8(mesh_i, mesh_o, norm_by_fracs, routehandle, frac_o, rc) + + ! input/output variables + type(ESMF_Mesh) , intent(in) :: mesh_i + type(ESMF_Mesh) , intent(in) :: mesh_o + ! If norm_by_fracs is .true., then remapping is done using ESMF_NORMTYPE_FRACAREA; + ! otherwise, remapping is done using ESMF_NORMTYPE_DSTAREA. FRACAREA normalization + ! adds a normalization factor of the fraction of the unmasked source grid that + ! overlaps with a destination cell. FRACAREA normalization is appropriate when you + ! want to treat values outside the mask as missing values that shouldn't contribute + ! to the average (this is appropriate for most fields); DSTAREA normalization is + ! appropriate when you want to treat values outside the mask as 0 (this is + ! appropriate for PCT cover fields where we want the final value to be expressed as + ! percent of the entire gridcell area). + logical , intent(in) :: norm_by_fracs + type(ESMF_RouteHandle) , intent(inout) :: routehandle + real(r8), optional , intent(inout) :: frac_o(:) + integer , intent(out) :: rc + + ! local variables + integer :: srcMaskValue = 0 ! ignore source points where the mesh mask is 0 + integer :: dstMaskValue = -987987 ! don't ingore any destination points + integer :: srcTermProcessing_Value = 0 + type(ESMF_NormType_Flag) :: normtype + type(ESMF_Field) :: field_i + type(ESMF_Field) :: field_o + type(ESMF_Field) :: dstfracfield + real(r8), pointer :: dataptr(:) + character(len=*), parameter :: subname = 'create_routehandle_r8' + ! -------------------------------------------- + + rc = ESMF_SUCCESS + + field_i = ESMF_FieldCreate(mesh_i, ESMF_TYPEKIND_R8, meshloc=ESMF_MESHLOC_ELEMENT, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + field_o = ESMF_FieldCreate(mesh_o, ESMF_TYPEKIND_R8, meshloc=ESMF_MESHLOC_ELEMENT, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + dstfracfield = ESMF_FieldCreate(mesh_o, ESMF_TYPEKIND_R8, meshloc=ESMF_MESHLOC_ELEMENT, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + if (norm_by_fracs) then + normtype = ESMF_NORMTYPE_FRACAREA + else + normtype = ESMF_NORMTYPE_DSTAREA + end if + + ! Create route handle to map field_model to field_data + call ESMF_FieldRegridStore(field_i, field_o, routehandle=routehandle, & + regridmethod=ESMF_REGRIDMETHOD_CONSERVE, normType=normtype, & + srcMaskValues=(/srcMaskValue/), & + dstMaskValues=(/dstMaskValue/), & + srcTermProcessing=srcTermProcessing_Value, & + ignoreDegenerate=.true., unmappedaction=ESMF_UNMAPPEDACTION_IGNORE, & + dstFracField= dstFracField, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After regridstore in "//trim(subname)) + + call ESMF_FieldGet(dstfracfield, farrayptr=dataptr, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + if (present(frac_o)) then + frac_o(:) = dataptr(:) + end if + + call ESMF_FieldDestroy(field_i, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + call ESMF_FieldDestroy(field_o, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + call ESMF_FieldDestroy(dstfracfield, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + + end subroutine create_routehandle_r8 + + !=============================================================== + subroutine regrid_rawdata1d_r4(mesh_i, mesh_o, routehandle, data_i, data_o, rc) + + ! input/output variables + type(ESMF_Mesh) , intent(in) :: mesh_i + type(ESMF_Mesh) , intent(in) :: mesh_o + type(ESMF_RouteHandle) , intent(inout) :: routehandle + real(r4) , intent(in) :: data_i(:) + real(r4) , intent(inout) :: data_o(:) + integer , intent(out) :: rc + + ! local variables + type(ESMF_Field) :: field_i + type(ESMF_Field) :: field_o + real(r4), pointer :: dataptr(:) + logical :: checkflag = .false. + character(len=*), parameter :: subname = 'regrid_rawdata1d_r4' + ! -------------------------------------------- + + rc = ESMF_SUCCESS + + field_i = ESMF_FieldCreate(mesh_i, ESMF_TYPEKIND_R4, meshloc=ESMF_MESHLOC_ELEMENT, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + field_o = ESMF_FieldCreate(mesh_o, ESMF_TYPEKIND_R4, meshloc=ESMF_MESHLOC_ELEMENT, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! Interpolate data_i to data_o + call ESMF_FieldGet(field_i, farrayptr=dataptr, rc=rc) + dataptr(:) = data_i(:) + call ESMF_FieldGet(field_o, farrayptr=dataptr, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + dataptr(:) = 0._r8 + call ESMF_FieldRegrid(field_i, field_o, routehandle=routehandle, & + termorderflag=ESMF_TERMORDER_SRCSEQ, checkflag=checkflag, zeroregion=ESMF_REGION_TOTAL, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_FieldGet(field_o, farrayptr=dataptr, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + data_o(:) = dataptr(:) + + call ESMF_FieldDestroy(field_i, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + call ESMF_FieldDestroy(field_o, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + + end subroutine regrid_rawdata1d_r4 + + !=============================================================== + subroutine regrid_rawdata1d_r8(mesh_i, mesh_o, routehandle, data_i, data_o, rc) + + ! input/output variables + type(ESMF_Mesh) , intent(in) :: mesh_i + type(ESMF_Mesh) , intent(in) :: mesh_o + type(ESMF_RouteHandle) , intent(inout) :: routehandle + real(r8) , intent(in) :: data_i(:) + real(r8) , intent(inout) :: data_o(:) + integer , intent(out) :: rc + + ! local variables + type(ESMF_Field) :: field_i + type(ESMF_Field) :: field_o + real(r8), pointer :: dataptr(:) + logical :: checkflag = .false. + character(len=*), parameter :: subname = 'regrid_rawdata1d_r8' + ! -------------------------------------------- + + rc = ESMF_SUCCESS + + field_i = ESMF_FieldCreate(mesh_i, ESMF_TYPEKIND_R8, meshloc=ESMF_MESHLOC_ELEMENT, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + field_o = ESMF_FieldCreate(mesh_o, ESMF_TYPEKIND_R8, meshloc=ESMF_MESHLOC_ELEMENT, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! Interpolate data_i to data_o + call ESMF_FieldGet(field_i, farrayptr=dataptr, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + dataptr(:) = data_i(:) + call ESMF_FieldGet(field_o, farrayptr=dataptr, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + dataptr(:) = 0._r8 + call ESMF_FieldRegrid(field_i, field_o, routehandle=routehandle, & + termorderflag=ESMF_TERMORDER_SRCSEQ, checkflag=checkflag, zeroregion=ESMF_REGION_TOTAL, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_FieldGet(field_o, farrayptr=dataptr, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + data_o(:) = dataptr(:) + + call ESMF_FieldDestroy(field_i, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + call ESMF_FieldDestroy(field_o, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + + end subroutine regrid_rawdata1d_r8 + + !=============================================================== + subroutine regrid_rawdata2d_r4(mesh_i, mesh_o, routehandle, data_i, data_o, lbound, ubound, rc) + + ! input/output variables + type(ESMF_Mesh) , intent(in) :: mesh_i + type(ESMF_Mesh) , intent(in) :: mesh_o + type(ESMF_RouteHandle) , intent(inout) :: routehandle + real(r4) , intent(in) :: data_i(:,:) + real(r4) , intent(inout) :: data_o(:,:) + integer , intent(in) :: lbound + integer , intent(in) :: ubound + integer , intent(out) :: rc + + ! local variables + type(ESMF_Field) :: field_i + type(ESMF_Field) :: field_o + logical :: checkflag = .false. + real(r4), pointer :: dataptr(:,:) + ! -------------------------------------------- + + rc = ESMF_SUCCESS + + field_i = ESMF_FieldCreate(mesh_i, ESMF_TYPEKIND_R4, meshloc=ESMF_MESHLOC_ELEMENT, & + ungriddedLbound=(/lbound/), ungriddedUbound=(/ubound/), gridToFieldMap=(/2/), rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + field_o = ESMF_FieldCreate(mesh_o, ESMF_TYPEKIND_R4, meshloc=ESMF_MESHLOC_ELEMENT, & + ungriddedLbound=(/lbound/), ungriddedUbound=(/ubound/), gridToFieldMap=(/2/), rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! Interpolate data_i to data_o + call ESMF_FieldGet(field_i, farrayptr=dataptr, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + dataptr(:,:) = data_i(:,:) + call ESMF_FieldGet(field_o, farrayptr=dataptr, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + dataptr(:,:) = 0._r8 + call ESMF_FieldRegrid(field_i, field_o, routehandle=routehandle, & + termorderflag=ESMF_TERMORDER_SRCSEQ, checkflag=checkflag, zeroregion=ESMF_REGION_TOTAL, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_FieldGet(field_o, farrayptr=dataptr, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + data_o(:,:) = dataptr(:,:) + + call ESMF_FieldDestroy(field_i, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + call ESMF_FieldDestroy(field_o, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + + end subroutine regrid_rawdata2d_r4 + + !=============================================================== + subroutine regrid_rawdata2d_r8(mesh_i, mesh_o, routehandle, data_i, data_o, lbound, ubound, rc) + + ! input/output variables + type(ESMF_Mesh) , intent(in) :: mesh_i + type(ESMF_Mesh) , intent(in) :: mesh_o + type(ESMF_RouteHandle) , intent(inout) :: routehandle + real(r8) , intent(in) :: data_i(:,:) + real(r8) , intent(inout) :: data_o(:,:) + integer , intent(in) :: lbound + integer , intent(in) :: ubound + integer , intent(out) :: rc + + ! local variables + type(ESMF_Field) :: field_i + type(ESMF_Field) :: field_o + logical :: checkflag = .false. + real(r8), pointer :: dataptr(:,:) + ! -------------------------------------------- + + rc = ESMF_SUCCESS + + field_i = ESMF_FieldCreate(mesh_i, ESMF_TYPEKIND_R8, meshloc=ESMF_MESHLOC_ELEMENT, & + ungriddedLbound=(/lbound/), ungriddedUbound=(/ubound/), gridToFieldMap=(/2/), rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + field_o = ESMF_FieldCreate(mesh_o, ESMF_TYPEKIND_R8, meshloc=ESMF_MESHLOC_ELEMENT, & + ungriddedLbound=(/lbound/), ungriddedUbound=(/ubound/), gridToFieldMap=(/2/), rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! Interpolate data_i to data_o + call ESMF_FieldGet(field_i, farrayptr=dataptr, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + dataptr(:,:) = data_i(:,:) + call ESMF_FieldGet(field_o, farrayptr=dataptr, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + dataptr(:,:) = 0._r8 + + call ESMF_FieldRegrid(field_i, field_o, routehandle=routehandle, & + termorderflag=ESMF_TERMORDER_SRCSEQ, checkflag=checkflag, zeroregion=ESMF_REGION_TOTAL, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_FieldGet(field_o, farrayptr=dataptr, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + data_o(:,:) = dataptr(:,:) + + call ESMF_FieldDestroy(field_i, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + call ESMF_FieldDestroy(field_o, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + + end subroutine regrid_rawdata2d_r8 + + !=============================================================== + subroutine get_meshareas(mesh, areas, rc) + + use mkvarpar, only : re + + ! input/output variables + type(ESMF_Mesh) , intent(in) :: mesh + real(r8) , intent(inout) :: areas(:) + integer , intent(out) :: rc + + ! local variables + real(r8), pointer :: dataptr(:) + type(ESMF_Field) :: lfield + ! -------------------------------------------- + + rc = ESMF_SUCCESS + + lfield = ESMF_FieldCreate(mesh, ESMF_TYPEKIND_R8, meshloc=ESMF_MESHLOC_ELEMENT, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_FieldRegridGetArea(lfield, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_FieldGet(lfield, farrayPtr=dataptr, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + areas(:) = dataptr(:) * re**2 + + call ESMF_FieldDestroy(lfield, nogarbage = .true., rc=rc) + + end subroutine get_meshareas + +end module mkesmfMod diff --git a/tools/mksurfdata_esmf/src/mkfileMod.F90 b/tools/mksurfdata_esmf/src/mkfileMod.F90 new file mode 100644 index 0000000000..e22394e1e1 --- /dev/null +++ b/tools/mksurfdata_esmf/src/mkfileMod.F90 @@ -0,0 +1,863 @@ +module mkfileMod + + use ESMF + use pio + use shr_kind_mod , only : r8 => shr_kind_r8, r4=> shr_kind_r4 + use shr_sys_mod , only : shr_sys_abort + use mkutilsMod , only : get_filename, chkerr + use mkvarpar , only : nlevsoi, numrad, numstdpft + use mkurbanparMod , only : numurbl, nlevurb, mkurbanpar + use mkpftConstantsMod , only : num_cft, num_natpft + use mkpioMod + use mkinputMod + use mkvarctl + + implicit none + private + + public :: mkfile_define_dims + public :: mkfile_define_atts + public :: mkfile_define_vars + public :: mkfile_output + + interface mkfile_output + module procedure mkfile_output_int1d + module procedure mkfile_output_int2d + module procedure mkfile_output_real1dr8 + module procedure mkfile_output_real2dr8 + module procedure mkfile_output_real1dr4 + module procedure mkfile_output_real2dr4 + end interface mkfile_output + + character(len=*) , parameter :: u_FILE_u = & + __FILE__ + +!================================================================================= +contains +!================================================================================= + + subroutine mkfile_define_dims(pioid, nx, ny, dynlanduse) + ! + ! Define dimensions. + ! + ! input/output variables + type(file_desc_t) , intent(in) :: pioid + integer , intent(in) :: nx, ny + logical , intent(in) :: dynlanduse + + ! local variables + integer :: dimid ! temporary + integer :: rcode ! error status + integer :: pftsize + integer :: natpftsize + character(len=*), parameter :: subname = 'mkfile_define_dims' + !----------------------------------------------------------------------- + + call ESMF_LogWrite(subname//' defining dimensions', ESMF_LOGMSG_INFO) + + if (outnc_1d) then + rcode = pio_def_dim(pioid, 'gridcell', nx, dimid) + else + rcode = pio_def_dim(pioid, 'lsmlon', nx, dimid) + rcode = pio_def_dim(pioid, 'lsmlat', ny, dimid) + end if + rcode = pio_def_dim(pioid, 'nlevsoi', nlevsoi , dimid) + rcode = pio_def_dim(pioid, 'nlevurb', nlevurb , dimid) + rcode = pio_def_dim(pioid, 'numurbl', numurbl , dimid) + rcode = pio_def_dim(pioid, 'numrad' , numrad, dimid) + if (.not. dynlanduse) then + rcode = pio_def_dim(pioid, 'nglcec' , nglcec , dimid) + rcode = pio_def_dim(pioid, 'nglcecp1', nglcec+1, dimid) + end if + rcode = pio_def_dim(pioid, 'time' , PIO_UNLIMITED , dimid) + rcode = pio_def_dim(pioid, 'nchar' , 256 , dimid) + + if (.not. dynlanduse) then + pftsize = numpft + 1 + rcode = pio_def_dim(pioid, 'lsmpft' , pftsize, dimid) + end if + natpftsize = num_natpft + 1 + rcode = pio_def_dim (pioid, 'natpft', natpftsize, dimid) + + ! zero-size dimensions can cause problems, so we only include the + ! cft dimension if num_cft > 0 Note that this implies that we can + ! only include PCT_CFT on the dataset if num_cft > 0 + if (num_cft > 0) then + rcode = pio_def_dim (pioid, 'cft', num_cft, dimid) + end if + + end subroutine mkfile_define_dims + + !================================================================================= + subroutine mkfile_define_atts(pioid, dynlanduse) + + ! input/output variables + type(file_desc_t) , intent(in) :: pioid + logical , intent(in) :: dynlanduse + + ! local variables + integer :: values(8) ! temporary + character(len=256) :: str ! global attribute string + character(len=256) :: name ! name of attribute + character(len=256) :: unit ! units of attribute + character(len= 18) :: datetime ! temporary + character(len= 8) :: date ! temporary + character(len= 10) :: time ! temporary + character(len= 5) :: zone ! temporary + integer :: rcode + character(len=*), parameter :: subname = 'mkfile_define_atts' + !----------------------------------------------------------------------- + + !--------------------------- + ! Set global attributes. + !--------------------------- + + call ESMF_LogWrite(subname//'setting global attributes', ESMF_LOGMSG_INFO) + + str = 'NCAR-CESM' + rcode = pio_put_att(pioid, pio_global, "Conventions", trim(str)) + + call date_and_time (date, time, zone, values) + datetime(1:8) = date(5:6) // '-' // date(7:8) // '-' // date(3:4) + datetime(9:) = ' ' // time(1:2) // ':' // time(3:4) // ':' // time(5:6) // ' ' + str = 'created on: ' // datetime + rcode = pio_put_att (pioid, pio_global, 'History_Log', trim(str)) + + str = 'Community Land Model: CLM5' + rcode = pio_put_att (pioid, pio_global, 'Source', trim(str)) + rcode = pio_put_att (pioid, pio_global, 'Version', trim(gitdescribe)) + rcode = pio_put_att (pioid, pio_global, 'Logname', trim(logname)) + rcode = pio_put_att (pioid, pio_global, 'Host', trim(hostname)) + rcode = pio_put_att (pioid, pio_global, 'Number-of-tasks', npes) + + ! TODO: check that this works + !rcode = pio_put_att_int(pioid, pio_global, 'nglcec', nglcec) + + ! Raw data file names + str = get_filename(mksrf_fgrid_mesh) + rcode = pio_put_att(pioid, pio_global, 'Input_grid_dataset', trim(str)) + str = get_filename(mksrf_fpctlak) + rcode = pio_put_att(pioid, pio_global, 'Percent_lake_raw_data_file_name', trim(str)) + str = get_filename(mksrf_flakdep) + rcode = pio_put_att(pioid, pio_global, 'Lake_depth_raw_data_file_name', trim(str)) + str = get_filename(mksrf_fwetlnd) + rcode = pio_put_att(pioid, pio_global, 'Inland_wetland_raw_data_file_name', trim(str)) + str = get_filename(mksrf_fglacier) + rcode = pio_put_att(pioid, pio_global, 'Glacier_raw_data_file_name', trim(str)) + str = get_filename(mksrf_fglacierregion) + rcode = pio_put_att(pioid, pio_global, 'Glacier_region_raw_data_file_name', trim(str)) + str = get_filename(mksrf_furbtopo) + rcode = pio_put_att(pioid, pio_global, 'Urban_Topography_raw_data_file_name', trim(str)) + str = get_filename(mksrf_furban) + rcode = pio_put_att(pioid, pio_global, 'Urban_raw_data_file_name', trim(str)) + str = get_filename(mksrf_fvegtyp) + rcode = pio_put_att(pioid, pio_global, 'Vegetation_type_raw_data_filename', trim(str)) + str = get_filename(mksrf_fabm) + rcode = pio_put_att(pioid, pio_global, 'agfirepkmon_raw_data_file_name', trim(str)) + str = get_filename(mksrf_fgdp) + rcode = pio_put_att(pioid, pio_global, 'gdp_raw_data_file_name', trim(str)) + str = get_filename(mksrf_fpeat) + rcode = pio_put_att(pioid, pio_global, 'peatland_raw_data_file_name', trim(str)) + str = get_filename(mksrf_fsoildepth) + rcode = pio_put_att(pioid, pio_global, 'soildepth_raw_data_file_name', trim(str)) + str = get_filename(mksrf_ftopostats) + rcode = pio_put_att(pioid, pio_global, 'topography_stats_raw_data_file_name', trim(str)) + if ( outnc_vic )then + str = get_filename(mksrf_fvic) + rcode = pio_put_att(pioid, pio_global, 'vic_raw_data_file_name', trim(str)) + end if + + ! Mesh file names + str = get_filename(mksrf_fvegtyp_mesh) + rcode = pio_put_att(pioid, pio_global, 'mesh_pft_file_name', trim(str)) + str = get_filename(mksrf_fpctlak_mesh) + rcode = pio_put_att(pioid, pio_global, 'mesh_pctlak_file', trim(str)) + str = get_filename(mksrf_flakdep_mesh) + rcode = pio_put_att(pioid, pio_global, 'mesh_lakdep_file', trim(str)) + str = get_filename(mksrf_fwetlnd_mesh) + rcode = pio_put_att(pioid, pio_global, 'mesh_wetlnd_file', trim(str)) + str = get_filename(mksrf_fglacier_mesh) + rcode = pio_put_att(pioid, pio_global, 'mesh_glacier_file', trim(str)) + str = get_filename(mksrf_fglacierregion_mesh) + rcode = pio_put_att(pioid, pio_global, 'mesh_glacier_region_file', trim(str)) + str = get_filename(mksrf_fsoitex_mesh) + rcode = pio_put_att(pioid, pio_global, 'mesh_soil_texture_file', trim(str)) + str = get_filename(mksrf_fsoicol_mesh) + rcode = pio_put_att(pioid, pio_global, 'mesh_soil_color_file', trim(str)) + str = get_filename(mksrf_furban_mesh) + rcode = pio_put_att(pioid, pio_global, 'mesh_urban_file', trim(str)) + str = get_filename(mksrf_fmax_mesh) + rcode = pio_put_att(pioid, pio_global, 'mesh_fmax_file', trim(str)) + str = get_filename(mksrf_fvocef_mesh) + rcode = pio_put_att(pioid, pio_global, 'mesh_VOC_EF_file', trim(str)) + str = get_filename(mksrf_fhrvtyp_mesh) + rcode = pio_put_att(pioid, pio_global, 'mesh_harvest_file', trim(str)) + if ( numpft == numstdpft )then + str = get_filename(mksrf_flai_mesh) + rcode = pio_put_att(pioid, pio_global, 'mesh_lai_sai_file', trim(str)) + end if + str = get_filename(mksrf_furbtopo_mesh) + rcode = pio_put_att(pioid, pio_global, 'mesh_urban_topography_file', trim(str)) + str = get_filename(mksrf_fabm_mesh) + rcode = pio_put_att(pioid, pio_global, 'mesh_agfirepkmon_file', trim(str)) + str = get_filename(mksrf_fgdp_mesh) + rcode = pio_put_att(pioid, pio_global, 'mesh_gdp_file', trim(str)) + str = get_filename(mksrf_fpeat_mesh) + rcode = pio_put_att(pioid, pio_global, 'mesh_peatland_file', trim(str)) + str = get_filename(mksrf_fsoildepth_mesh) + rcode = pio_put_att(pioid, pio_global, 'mesh_soildepth_file', trim(str)) + str = get_filename(mksrf_ftopostats_mesh) + rcode = pio_put_att(pioid, pio_global, 'mesh_topography_stats_file', trim(str)) + if ( outnc_vic )then + str = get_filename(mksrf_fvic_mesh) + rcode = pio_put_att(pioid, pio_global, 'mesh_vic_file', trim(str)) + end if + + if (.not. dynlanduse) then + str = get_filename(mksrf_flai) + rcode = pio_put_att(pioid, pio_global, 'lai_raw_data_file_name', trim(str)) + str = get_filename(mksrf_fsoicol) + rcode = pio_put_att(pioid, pio_global, 'soil_color_raw_data_file_name', trim(str)) + str = get_filename(mksrf_fsoitex) + rcode = pio_put_att(pioid, pio_global, 'soil_texture_mapunit_raw_data_file_name', trim(str)) + str = get_filename(mksrf_fsoitex_lookup) + rcode = pio_put_att(pioid, pio_global, 'soil_texture_lookup_raw_data_file_name', trim(str)) + str = get_filename(mksrf_fmax) + rcode = pio_put_att(pioid, pio_global, 'fmax_raw_data_file_name', trim(str)) + str = get_filename(mksrf_fvocef) + rcode = pio_put_att(pioid, pio_global, 'VOC_EF_raw_data_file_name', trim(str)) + end if + + end subroutine mkfile_define_atts + + !================================================================================= + subroutine mkfile_define_vars(pioid, dynlanduse) + + ! Define fsurdat variables + + ! input/output variables + type(file_desc_t) , intent(in) :: pioid + logical , intent(in) :: dynlanduse + + ! local variables + integer :: xtype ! external type + character(len=*), parameter :: subname = 'mkfile_define_vars' + !----------------------------------------------------------------------- + + if ( outnc_double ) then + xtype = PIO_DOUBLE + else + xtype = PIO_REAL + end if + + call mkpio_def_spatial_var(pioid=pioid, varname='LONGXY', xtype=xtype, & + long_name='longitude', units='degrees east') + + call mkpio_def_spatial_var(pioid=pioid, varname='LATIXY', xtype=xtype, & + long_name='latitude', units='degrees north') + + if (.not. dynlanduse) then + + call mkpio_defvar(pioid=pioid, varname='mxsoil_color', xtype=PIO_INT, & + long_name='maximum numbers of soil colors', units='unitless') + + call mkpio_def_spatial_var(pioid=pioid, varname='SOIL_COLOR', xtype=PIO_INT, & + long_name='soil color', units='unitless') + + call mkpio_def_spatial_var(pioid=pioid, varname='PCT_SAND', xtype=PIO_REAL, & + lev1name='nlevsoi', & + long_name='percent sand', units='unitless') + + call mkpio_def_spatial_var(pioid=pioid, varname='PCT_CLAY', xtype=PIO_REAL, & + lev1name='nlevsoi', & + long_name='percent clay', units='unitless') + + call mkpio_def_spatial_var(pioid=pioid, varname='mapunits', xtype=PIO_INT, & + long_name='soil texture map units', units='unitless') + + call mkpio_def_spatial_var(pioid=pioid, varname='ORGANIC', xtype=PIO_REAL, & + lev1name='nlevsoi', & + long_name='organic matter density at soil levels', & + units='kg/m3 (assumed carbon content 0.58 gC per gOM)') + call mkpio_def_spatial_var(pioid=pioid, varname='ORGC', xtype=PIO_REAL, & + lev1name='nlevsoi', & + long_name='soil organic carbon', units='gC/kg soil') + + call mkpio_def_spatial_var(pioid=pioid, varname='BULK', xtype=PIO_REAL, & + lev1name='nlevsoi', & + long_name='bulk density', units='g cm-3') + + call mkpio_def_spatial_var(pioid=pioid, varname='CFRAG', xtype=PIO_REAL, & + lev1name='nlevsoi', & + long_name='coarse fragments', units='vol% > 2 mm') + + call mkpio_def_spatial_var(pioid=pioid, varname='PHAQ', xtype=PIO_REAL, & + lev1name='nlevsoi', & + long_name='pH measured in water', units='unitless') + + call mkpio_def_spatial_var(pioid=pioid, varname='FMAX', xtype=xtype, & + long_name='maximum fractional saturated area', units='unitless') + + call mkpio_def_spatial_var(pioid=pioid, varname='EF1_BTR', xtype=xtype, & + long_name='EF btr (isoprene)', units='unitless') + + call mkpio_def_spatial_var(pioid=pioid, varname='EF1_FET', xtype=xtype, & + long_name='EF fet (isoprene)', units='unitless') + + call mkpio_def_spatial_var(pioid=pioid, varname='EF1_FDT', xtype=xtype, & + long_name='EF fdt (isoprene)', units='unitless') + + call mkpio_def_spatial_var(pioid=pioid, varname='EF1_SHR', xtype=xtype, & + long_name='EF shr (isoprene)', units='unitless') + + call mkpio_def_spatial_var(pioid=pioid, varname='EF1_GRS', xtype=xtype, & + long_name='EF grs (isoprene)', units='unitless') + + call mkpio_def_spatial_var(pioid=pioid, varname='EF1_CRP', xtype=xtype, & + long_name='EF crp (isoprene)', units='unitless') + + call mkpio_def_spatial_var(pioid=pioid, varname='CANYON_HWR', xtype=xtype, & + lev1name='numurbl', & + long_name='canyon height to width ratio', units='unitless') + + call mkpio_def_spatial_var(pioid=pioid, varname='EM_IMPROAD', xtype=xtype, & + lev1name='numurbl', & + long_name='emissivity of impervious road', units='unitless') + + call mkpio_def_spatial_var(pioid=pioid, varname='EM_PERROAD', xtype=xtype, & + lev1name='numurbl', & + long_name='emissivity of pervious road', units='unitless') + + call mkpio_def_spatial_var(pioid=pioid, varname='EM_ROOF', xtype=xtype, & + lev1name='numurbl', & + long_name='emissivity of roof', units='unitless') + + call mkpio_def_spatial_var(pioid=pioid, varname='EM_WALL', xtype=xtype, & + lev1name='numurbl', & + long_name='emissivity of wall', units='unitless') + + call mkpio_def_spatial_var(pioid=pioid, varname='HT_ROOF', xtype=xtype, & + lev1name='numurbl', & + long_name='height of roof', units='meters') + + call mkpio_def_spatial_var(pioid=pioid, varname='THICK_ROOF', xtype=xtype, & + lev1name='numurbl', & + long_name='thickness of roof', units='meters') + + call mkpio_def_spatial_var(pioid=pioid, varname='THICK_WALL', xtype=xtype, & + lev1name='numurbl', & + long_name='thickness of wall', units='meters') + + call mkpio_def_spatial_var(pioid=pioid, varname='T_BUILDING_MIN', xtype=xtype, & + lev1name='numurbl', & + long_name='minimum interior building temperature', units='K') + + call mkpio_def_spatial_var(pioid=pioid, varname='WIND_HGT_CANYON', xtype=xtype, & + lev1name='numurbl', & + long_name='height of wind in canyon', units='meters') + + call mkpio_def_spatial_var(pioid=pioid, varname='WTLUNIT_ROOF', xtype=xtype, & + lev1name='numurbl', & + long_name='fraction of roof', units='unitless') + + call mkpio_def_spatial_var(pioid=pioid, varname='WTROAD_PERV', xtype=xtype, & + lev1name='numurbl', & + long_name='fraction of pervious road', units='unitless') + + call mkpio_def_spatial_var(pioid=pioid, varname='ALB_IMPROAD_DIR', xtype=xtype, & + lev1name='numurbl', lev2name='numrad', & + long_name='direct albedo of impervious road', units='unitless') + + call mkpio_def_spatial_var(pioid=pioid, varname='ALB_IMPROAD_DIF', xtype=xtype, & + lev1name='numurbl', lev2name='numrad', & + long_name='diffuse albedo of impervious road', units='unitless') + + call mkpio_def_spatial_var(pioid=pioid, varname='ALB_PERROAD_DIR', xtype=xtype, & + lev1name='numurbl', lev2name='numrad', & + long_name='direct albedo of pervious road', units='unitless') + + call mkpio_def_spatial_var(pioid=pioid, varname='ALB_PERROAD_DIF', xtype=xtype, & + lev1name='numurbl', lev2name='numrad', & + long_name='diffuse albedo of pervious road', units='unitless') + + call mkpio_def_spatial_var(pioid=pioid, varname='ALB_ROOF_DIR', xtype=xtype, & + lev1name='numurbl', lev2name='numrad', & + long_name='direct albedo of roof', units='unitless') + + call mkpio_def_spatial_var(pioid=pioid, varname='ALB_ROOF_DIF', xtype=xtype, & + lev1name='numurbl', lev2name='numrad', & + long_name='diffuse albedo of roof', units='unitless') + + call mkpio_def_spatial_var(pioid=pioid, varname='ALB_WALL_DIR', xtype=xtype, & + lev1name='numurbl', lev2name='numrad', & + long_name='direct albedo of wall', units='unitless') + + call mkpio_def_spatial_var(pioid=pioid, varname='ALB_WALL_DIF', xtype=xtype, & + lev1name='numurbl', lev2name='numrad', & + long_name='diffuse albedo of wall', units='unitless') + + call mkpio_def_spatial_var(pioid=pioid, varname='TK_ROOF', xtype=xtype, & + lev1name='numurbl', lev2name='nlevurb', & + long_name='thermal conductivity of roof', units='W/m*K') + + call mkpio_def_spatial_var(pioid=pioid, varname='TK_WALL', xtype=xtype, & + lev1name='numurbl', lev2name='nlevurb', & + long_name='thermal conductivity of wall', units='W/m*K') + + call mkpio_def_spatial_var(pioid=pioid, varname='TK_IMPROAD', xtype=xtype, & + lev1name='numurbl', lev2name='nlevurb', & + long_name='thermal conductivity of impervious road', units='W/m*K') + + call mkpio_def_spatial_var(pioid=pioid, varname='CV_ROOF', xtype=xtype, & + lev1name='numurbl', lev2name='nlevurb', & + long_name='volumetric heat capacity of roof', units='J/m^3*K') + + call mkpio_def_spatial_var(pioid=pioid, varname='CV_WALL', xtype=xtype, & + lev1name='numurbl', lev2name='nlevurb', & + long_name='volumetric heat capacity of wall', units='J/m^3*K') + + call mkpio_def_spatial_var(pioid=pioid, varname='CV_IMPROAD', xtype=xtype, & + lev1name='numurbl', lev2name='nlevurb', & + long_name='volumetric heat capacity of impervious road', units='J/m^3*K') + + call mkpio_def_spatial_var(pioid=pioid, varname='NLEV_IMPROAD', xtype=PIO_INT, & + lev1name='numurbl', & + long_name='number of impervious road layers', units='unitless') + + call mkpio_def_spatial_var(pioid=pioid, varname='peatf', xtype=xtype, & + long_name='peatland fraction', units='unitless') + + call mkpio_def_spatial_var(pioid=pioid, varname='zbedrock', xtype=xtype, & + long_name='soil depth', units='m') + + call mkpio_def_spatial_var(pioid=pioid, varname='abm', xtype=PIO_INT, & + long_name='agricultural fire peak month', units='month') + + call mkpio_def_spatial_var(pioid=pioid, varname='gdp', xtype=xtype, & + long_name='gdp', units='k 1995US$ capita-1') + + call mkpio_def_spatial_var(pioid=pioid, varname='SLOPE', xtype=PIO_REAL, & + long_name='mean topographic slope', units='degrees') + + call mkpio_def_spatial_var(pioid=pioid, varname='STD_ELEV', xtype=PIO_REAL, & + long_name='standard deviation of elevation', units='m') + + if ( outnc_vic )then + call mkpio_def_spatial_var(pioid=pioid, varname='binfl', xtype=xtype, & + long_name='VIC b parameter for the Variable Infiltration Capacity Curve', units='unitless') + + call mkpio_def_spatial_var(pioid=pioid, varname='Ws', xtype=xtype, & + long_name='VIC Ws parameter for the ARNO curve', units='unitless') + + call mkpio_def_spatial_var(pioid=pioid, varname='Dsmax', xtype=xtype, & + long_name='VIC Dsmax parameter for the ARNO curve', units='mm/day') + + call mkpio_def_spatial_var(pioid=pioid, varname='Ds', xtype=xtype, & + long_name='VIC Ds parameter for the ARNO curve', units='unitless') + + end if + + call mkpio_def_spatial_var(pioid=pioid, varname='PCT_OCEAN', xtype=xtype, & + long_name='percent ocean', units='unitless') + + call mkpio_def_spatial_var(pioid=pioid, varname='LAKEDEPTH', xtype=xtype, & + long_name='lake depth', units='m') + + call mkpio_def_spatial_var(pioid=pioid, varname='PCT_WETLAND', xtype=xtype, & + long_name='percent wetland', units='unitless') + + call mkpio_def_spatial_var(pioid=pioid, varname='PCT_LAKE', xtype=xtype, & + long_name='percent lake', units='unitless') + + call mkpio_def_spatial_var(pioid=pioid, varname='PCT_GLACIER', xtype=xtype, & + long_name='percent glacier', units='unitless') + + call mkpio_def_spatial_var(pioid=pioid, varname='GLACIER_REGION', xtype=PIO_INT, & + long_name='glacier region ID', units='unitless') + + call mkpio_defvar(pioid=pioid, varname='GLC_MEC', xtype=xtype, & + dim1name='nglcecp1', long_name='Glacier elevation class', units='m') + + call mkpio_def_spatial_var(pioid=pioid, varname='PCT_GLC_MEC', xtype=xtype, & + lev1name='nglcec', & + long_name='percent glacier for each glacier elevation class (% of landunit)', units='unitless') + + call mkpio_def_spatial_var(pioid=pioid, varname='TOPO_GLC_MEC', xtype=xtype, & + lev1name='nglcec', & + long_name='mean elevation on glacier elevation classes', units='m') + + if ( outnc_3dglc ) then + call mkpio_def_spatial_var(pioid=pioid, varname='PCT_GLC_MEC_GIC', xtype=xtype, & + lev1name='nglcec', & + long_name='percent smaller glaciers and ice caps for each glacier elevation class (% of landunit)', units='unitless') + + call mkpio_def_spatial_var(pioid=pioid, varname='PCT_GLC_MEC_ICESHEET', xtype=xtype, & + lev1name='nglcec', & + long_name='percent ice sheet for each glacier elevation class (% of landunit)', units='unitless') + + call mkpio_def_spatial_var(pioid=pioid, varname='PCT_GLC_GIC', xtype=xtype, & + long_name='percent ice caps/glaciers (% of landunit)', units='unitless') + + call mkpio_def_spatial_var(pioid=pioid, varname='PCT_GLC_ICESHEET', xtype=xtype, & + long_name='percent ice sheet (% of landunit)', units='unitless') + + end if + + call mkpio_def_spatial_var(pioid=pioid, varname='PCT_URBAN', xtype=xtype, & + lev1name='numurbl', & + long_name='percent urban for each density type', units='unitless') + + call mkpio_def_spatial_var(pioid=pioid, varname='URBAN_REGION_ID', xtype=PIO_INT, & + long_name='urban region ID', units='unitless') + + end if + + if (.not. dynlanduse) then + call mkpio_def_spatial_var(pioid=pioid, varname='CONST_HARVEST_VH1', xtype=xtype, & + long_name = "harvest from primary forest", units = "gC/m2/yr") + + call mkpio_def_spatial_var(pioid=pioid, varname='CONST_HARVEST_VH2', xtype=xtype, & + long_name = "harvest from primary non-forest", units = "gC/m2/yr") + + call mkpio_def_spatial_var(pioid=pioid, varname='CONST_HARVEST_SH1', xtype=xtype, & + long_name = "harvest from secondary mature-forest", units = "gC/m2/yr") + + call mkpio_def_spatial_var(pioid=pioid, varname='CONST_HARVEST_SH2', xtype=xtype, & + long_name = "harvest from secondary young-forest", units = "gC/m2/yr") + + call mkpio_def_spatial_var(pioid=pioid, varname='CONST_HARVEST_SH3', xtype=xtype, & + long_name = "harvest from secondary non-forest", units = "gC/m2/yr") + + call mkpio_def_spatial_var(pioid=pioid, varname='CONST_GRAZING', xtype=xtype, & + long_name = "grazing of herbacous pfts", units = "gC/m2/yr") + + call mkpio_def_spatial_var(pioid=pioid, varname='CONST_FERTNITRO_CFT', xtype=xtype, & + lev1name = 'cft', & + long_name = "nitrogen fertilizer for each crop", units = "gN/m2/yr") + + call mkpio_def_spatial_var(pioid=pioid, varname='UNREPRESENTED_PFT_LULCC', xtype=xtype,& + lev1name = 'natpft', & + long_name = "unrepresented PFT gross LULCC transitions", units = "unitless") + + call mkpio_def_spatial_var(pioid=pioid, varname='UNREPRESENTED_CFT_LULCC', xtype=xtype, & + lev1name = 'cft', & + long_name = "unrepresented crop gross LULCC transitions", units = "unitless") + + else + + call mkpio_def_spatial_var(pioid=pioid, varname='PCT_URBAN', xtype=xtype, & + lev1name = 'numurbl', lev2name='time', & + long_name = "percent urban for each density type", units = "unitless") + + call mkpio_def_spatial_var(pioid=pioid, varname='PCT_URBAN_MAX', xtype=xtype, & + lev1name = 'numurbl', & + long_name = "maximum percent urban for each density type", units = "unitless") + + call mkpio_def_spatial_var(pioid=pioid, varname='PCT_LAKE', xtype=xtype, & + lev1name = 'time', & + long_name = "percent lake", units = "unitless") + + call mkpio_def_spatial_var(pioid=pioid, varname='PCT_LAKE_MAX', xtype=xtype, & + long_name = "maximum percent lake", units = "unitless") + + call mkpio_def_spatial_var(pioid=pioid, varname='HARVEST_VH1', xtype=xtype, & + lev1name='time', & + long_name = "harvest from primary forest", units = "gC/m2/yr") + + call mkpio_def_spatial_var(pioid=pioid, varname='HARVEST_VH2', xtype=xtype, & + lev1name='time', & + long_name = "harvest from primary non-forest", units = "gC/m2/yr") + + call mkpio_def_spatial_var(pioid=pioid, varname='HARVEST_SH1', xtype=xtype, & + lev1name='time', & + long_name = "harvest from secondary mature-forest", units = "gC/m2/yr") + + call mkpio_def_spatial_var(pioid=pioid, varname='HARVEST_SH2', xtype=xtype, & + lev1name='time', & + long_name = "harvest from secondary young-forest", units = "gC/m2/yr") + + call mkpio_def_spatial_var(pioid=pioid, varname='HARVEST_SH3', xtype=xtype, & + lev1name='time', & + long_name = "harvest from secondary non-forest", units = "gC/m2/yr") + + call mkpio_def_spatial_var(pioid=pioid, varname='GRAZING', xtype=xtype, & + lev1name='time', & + long_name = "grazing of herbacous pfts", units = "gC/m2/yr") + + call mkpio_def_spatial_var(pioid=pioid, varname='FERTNITRO_CFT', xtype=xtype, & + lev1name = 'cft', lev2name='time', & + long_name = "nitrogen fertilizer for each crop", units = "gN/m2/yr") + + call mkpio_def_spatial_var(pioid=pioid, varname='UNREPRESENTED_PFT_LULCC', xtype=xtype, & + lev1name = 'natpft', lev2name='time', & + long_name = "unrepresented PFT gross LULCC transitions", units = "unitless") + + call mkpio_def_spatial_var(pioid=pioid, varname='UNREPRESENTED_CFT_LULCC', xtype=xtype, & + lev1name = 'cft', lev2name='time', & + long_name = "unrepresented crop gross LULCC transitions", units = "unitless") + end if ! .not. dynlanduse + + ! Coordinate variable for indices of natural PFTs + call mkpio_defvar(pioid=pioid, varname='natpft', xtype=PIO_INT, & + dim1name='natpft', long_name='indices of natural PFTs', units='index') + + ! Coordinate variable for indices of CFTs + if (num_cft > 0) then + call mkpio_defvar(pioid=pioid, varname='cft', xtype=PIO_INT, & + dim1name='cft', long_name='indices of CFTs', units='index') + end if + + call mkpio_def_spatial_var(pioid=pioid, varname='LANDFRAC_PFT', xtype=xtype, & + long_name='land fraction from pft dataset (DIFF FROM landfrac USED IN SIMULATION, SHOWN IN HISTORY)', units='unitless') + + if (.not. dynlanduse) then + call mkpio_def_spatial_var(pioid=pioid, varname='LANDFRAC_MKSURFDATA', xtype=xtype, & + long_name='land fraction used for renormalization of areas in mksurfdata (DIFF FROM landfrac USED IN SIMULATION)', & + units='unitless') + else + call mkpio_def_spatial_var(pioid=pioid, varname='LANDFRAC_MKSURFDATA', xtype=xtype, & + lev1name='time', & + long_name='land fraction used for renormalization of areas in mksurfdata (DIFF FROM landfrac USED IN SIMULATION)', & + units='unitless') + end if + + if (.not. dynlanduse) then + call mkpio_def_spatial_var(pioid=pioid, varname='PCT_NATVEG', xtype=xtype, & + long_name='total percent natural vegetation landunit', units='unitless') + end if + + if (.not. dynlanduse) then + call mkpio_def_spatial_var(pioid=pioid, varname='PCT_CROP', xtype=xtype, & + long_name='total percent crop landunit', units='unitless') + else + call mkpio_def_spatial_var(pioid=pioid, varname='PCT_CROP', xtype=xtype, & + lev1name='time', & + long_name='total percent crop landunit', units='unitless') + call mkpio_def_spatial_var(pioid=pioid, varname='PCT_CROP_MAX', xtype=xtype, & + long_name='maximum total percent crop landunit during time period', units='unitless') + end if + + if (.not. dynlanduse) then + call mkpio_def_spatial_var(pioid=pioid, varname='PCT_NAT_PFT', xtype=xtype, & + lev1name='natpft', & + long_name='percent plant functional type on the natural veg landunit (% of landunit)', units='unitless') + else + call mkpio_def_spatial_var(pioid=pioid, varname='PCT_NAT_PFT', xtype=xtype, & + lev1name='natpft', lev2name='time', & + long_name='percent plant functional type on the natural veg landunit (% of landunit)', units='unitless') + call mkpio_def_spatial_var(pioid=pioid, varname='PCT_NAT_PFT_MAX', xtype=xtype, & + lev1name='natpft', & + long_name='maximum percent plant functional type during time period (% of landunit)', units='unitless') + end if + + if (num_cft > 0) then + if (.not. dynlanduse) then + call mkpio_def_spatial_var(pioid=pioid, varname='PCT_CFT', xtype=xtype, & + lev1name='cft', & + long_name='percent crop functional type on the crop landunit (% of landunit)', units='unitless') + else + call mkpio_def_spatial_var(pioid=pioid, varname='PCT_CFT', xtype=xtype, & + lev1name='cft', lev2name='time', & + long_name='percent crop functional type on the crop landunit (% of landunit)', units='unitless') + call mkpio_def_spatial_var(pioid=pioid, varname='PCT_CFT_MAX', xtype=xtype, & + lev1name='cft', & + long_name='maximum percent crop functional type during time period (% of landunit)', units='unitless') + end if + end if + + if (.not. dynlanduse) then + call mkpio_def_spatial_var(pioid=pioid, varname='MONTHLY_LAI', xtype=xtype, & + lev1name='lsmpft', lev2name='time', & + long_name='monthly leaf area index', units='unitless') + + call mkpio_def_spatial_var(pioid=pioid, varname='MONTHLY_SAI', xtype=xtype, & + lev1name='lsmpft', lev2name='time', & + long_name='monthly stem area index', units='unitless') + + call mkpio_def_spatial_var(pioid=pioid, varname='MONTHLY_HEIGHT_TOP', xtype=xtype, & + lev1name='lsmpft', lev2name='time', & + long_name='monthly height top', units='meters') + + call mkpio_def_spatial_var(pioid=pioid, varname='MONTHLY_HEIGHT_BOT', xtype=xtype, & + lev1name='lsmpft', lev2name='time', & + long_name='monthly height bottom', units='meters') + end if + + if (dynlanduse) then + call mkpio_defvar(pioid=pioid, varname='YEAR', xtype=PIO_INT, & + dim1name='time', & + long_name='Year of PFT data', units='unitless') + call mkpio_defvar(pioid=pioid, varname='time', xtype=PIO_INT, & + dim1name='time', & + long_name='year', units='unitless') + call mkpio_defvar(pioid=pioid, varname='input_pftdata_filename', xtype=PIO_CHAR, & + dim1name='nchar', dim2name='time', & + long_name='Input filepath for PFT values for this year', units='unitless') + else + call mkpio_defvar(pioid=pioid, varname='time', xtype=PIO_INT, & + dim1name='time', & + long_name='Calendar month', units='month') + end if + + end subroutine mkfile_define_vars + + !================================================================================= + subroutine mkfile_output_int1d(pioid, mesh, varname, data, rc) + + ! input/output variables + type(file_desc_t) , intent(inout) :: pioid + type(ESMF_Mesh) , intent(in) :: mesh + character(len=*) , intent(in) :: varname + integer , intent(in) :: data(:) + integer , intent(out) :: rc + + ! local variables + type(io_desc_t) :: pio_iodesc + type(var_desc_t) :: pio_varid + integer :: rcode + !----------------------------------------------------------------------- + + rc = ESMF_SUCCESS + + call mkpio_iodesc_output(pioid, mesh, trim(varname), pio_iodesc, rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in generating an iodesc for '//trim(varname)) + rcode = pio_inq_varid(pioid, trim(varname), pio_varid) + call pio_write_darray(pioid, pio_varid, pio_iodesc, data, rcode) + call pio_freedecomp(pioid, pio_iodesc) + + end subroutine mkfile_output_int1d + + !================================================================================= + subroutine mkfile_output_int2d(pioid, mesh, varname, data, rc) + + ! input/output variables + type(file_desc_t) , intent(inout) :: pioid + type(ESMF_Mesh) , intent(in) :: mesh + character(len=*) , intent(in) :: varname + integer , intent(in) :: data(:,:) + integer , intent(out) :: rc + + ! local variables + type(io_desc_t) :: pio_iodesc + type(var_desc_t) :: pio_varid + integer :: rcode + !----------------------------------------------------------------------- + + rc = ESMF_SUCCESS + + call mkpio_iodesc_output(pioid, mesh, trim(varname), pio_iodesc, rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in generating an iodesc for '//trim(varname)) + rcode = pio_inq_varid(pioid, trim(varname), pio_varid) + call pio_write_darray(pioid, pio_varid, pio_iodesc, data, rcode) + call pio_freedecomp(pioid, pio_iodesc) + + end subroutine mkfile_output_int2d + + !================================================================================= + subroutine mkfile_output_real1dr8(pioid, mesh, varname, data, rc) + + ! input/output variables + type(file_desc_t) , intent(inout) :: pioid + type(ESMF_Mesh) , intent(in) :: mesh + character(len=*) , intent(in) :: varname + real(r8) , intent(in) :: data(:) + integer , intent(out) :: rc + + ! local variables + type(io_desc_t) :: pio_iodesc + type(var_desc_t) :: pio_varid + integer :: rcode + !----------------------------------------------------------------------- + + rc = ESMF_SUCCESS + + call mkpio_iodesc_output(pioid, mesh, trim(varname), pio_iodesc, rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in generating an iodesc for '//trim(varname)) + rcode = pio_inq_varid(pioid, trim(varname), pio_varid) + call pio_write_darray(pioid, pio_varid, pio_iodesc, data, rcode) + call pio_freedecomp(pioid, pio_iodesc) + + end subroutine mkfile_output_real1dr8 + + !================================================================================= + subroutine mkfile_output_real2dr8(pioid, mesh, varname, data, lev1name, rc) + + ! input/output variables + type(file_desc_t) , intent(inout) :: pioid + type(ESMF_Mesh) , intent(in) :: mesh + character(len=*) , intent(in) :: varname + real(r8) , intent(in) :: data(:,:) + integer , intent(out) :: rc + character(len=*) , optional, intent(in) :: lev1name + + ! local variables + type(io_desc_t) :: pio_iodesc + type(var_desc_t) :: pio_varid + integer :: rcode + !----------------------------------------------------------------------- + + rc = ESMF_SUCCESS + + call mkpio_iodesc_output(pioid, mesh, trim(varname), pio_iodesc, rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in generating an iodesc for '//trim(varname)) + rcode = pio_inq_varid(pioid, trim(varname), pio_varid) + call pio_write_darray(pioid, pio_varid, pio_iodesc, data, rcode) + call pio_freedecomp(pioid, pio_iodesc) + + end subroutine mkfile_output_real2dr8 + + !================================================================================= + subroutine mkfile_output_real1dr4(pioid, mesh, varname, data, rc) + + ! input/output variables + type(file_desc_t) , intent(inout) :: pioid + type(ESMF_Mesh) , intent(in) :: mesh + character(len=*) , intent(in) :: varname + real(r4) , intent(in) :: data(:) + integer , intent(out) :: rc + + ! local variables + type(io_desc_t) :: pio_iodesc + type(var_desc_t) :: pio_varid + integer :: rcode + !----------------------------------------------------------------------- + + rc = ESMF_SUCCESS + + call mkpio_iodesc_output(pioid, mesh, trim(varname), pio_iodesc, rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in generating an iodesc for '//trim(varname)) + rcode = pio_inq_varid(pioid, trim(varname), pio_varid) + call pio_write_darray(pioid, pio_varid, pio_iodesc, data, rcode) + call pio_freedecomp(pioid, pio_iodesc) + + end subroutine mkfile_output_real1dr4 + + !================================================================================= + subroutine mkfile_output_real2dr4(pioid, mesh, varname, data, lev1name, rc) + + ! input/output variables + type(file_desc_t) , intent(inout) :: pioid + type(ESMF_Mesh) , intent(in) :: mesh + character(len=*) , intent(in) :: varname + real(r4) , intent(in) :: data(:,:) + integer , intent(out) :: rc + character(len=*) , optional, intent(in) :: lev1name + + ! local variables + type(io_desc_t) :: pio_iodesc + type(var_desc_t) :: pio_varid + integer :: rcode + !----------------------------------------------------------------------- + + rc = ESMF_SUCCESS + + call mkpio_iodesc_output(pioid, mesh, trim(varname), pio_iodesc, rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in generating an iodesc for '//trim(varname)) + rcode = pio_inq_varid(pioid, trim(varname), pio_varid) + call pio_write_darray(pioid, pio_varid, pio_iodesc, data, rcode) + call pio_freedecomp(pioid, pio_iodesc) + + end subroutine mkfile_output_real2dr4 + +end module mkfileMod + diff --git a/tools/mksurfdata_esmf/src/mkgdpMod.F90 b/tools/mksurfdata_esmf/src/mkgdpMod.F90 new file mode 100644 index 0000000000..cb37de8bbd --- /dev/null +++ b/tools/mksurfdata_esmf/src/mkgdpMod.F90 @@ -0,0 +1,153 @@ +module mkgdpMod + + !----------------------------------------------------------------------- + ! make GDP from input GDP data + !----------------------------------------------------------------------- + + use ESMF + use pio , only : file_desc_t, pio_openfile, pio_closefile, pio_nowrite, pio_syncfile + use shr_kind_mod , only : r8 => shr_kind_r8, r4=>shr_kind_r4 + use shr_sys_mod , only : shr_sys_abort + use mkpioMod , only : mkpio_get_rawdata, pio_iotype, pio_iosystem + use mkesmfMod , only : regrid_rawdata, create_routehandle_r8 + use mkvarctl , only : ndiag, root_task, mpicom, spval + use mkdiagnosticsMod , only : output_diagnostics_continuous + use mkchecksMod , only : min_bad + use mkutilsMod , only : chkerr + use mkfileMod , only : mkfile_output + + implicit none + private + + public :: mkgdp ! regrid gdp data + + character(len=*) , parameter :: u_FILE_u = & + __FILE__ + +!=============================================================== +contains +!=============================================================== + + subroutine mkgdp(file_mesh_i, file_data_i, mesh_o, pioid_o, rc) + ! + ! make GDP from input GDP data + ! + ! input/output variables + character(len=*) , intent(in) :: file_mesh_i ! input mesh file name + character(len=*) , intent(in) :: file_data_i ! input data file name + type(ESMF_Mesh) , intent(in) :: mesh_o ! input model mesh + type(file_desc_t) , intent(inout) :: pioid_o + integer , intent(out) :: rc + + ! local variables: + type(ESMF_RouteHandle) :: routehandle + type(ESMF_Mesh) :: mesh_i + type(file_desc_t) :: pioid_i + integer :: ni,no,k + integer :: ns_i, ns_o + integer , allocatable :: mask_i(:) + real(r8), allocatable :: frac_i(:) + real(r8), allocatable :: frac_o(:) + real(r8), allocatable :: gdp_i(:) ! input grid: percent gdp + real(r8), allocatable :: gdp_o(:) ! output grid: GDP (x1000 1995 US$ per capita) + real(r8), parameter :: min_valid = 0._r8 ! minimum valid value + integer :: ier, rcode ! error status + character(len=*), parameter :: subname = 'mkgdp' + !----------------------------------------------------------------------- + + rc = ESMF_SUCCESS + + if (root_task) then + write(ndiag,*) + write(ndiag,'(1x,80a1)') ('=',k=1,80) + write(ndiag,*) + write(ndiag,'(a)') 'Attempting to make GDP.....' + write(ndiag,'(a)') ' Input file is '//trim(file_data_i) + write(ndiag,'(a)') ' Input mesh file is '//trim(file_mesh_i) + end if + call ESMF_VMLogMemInfo("At start of"//trim(subname)) + + ! Open input data file + rcode = pio_openfile(pio_iosystem, pioid_i, pio_iotype, trim(file_data_i), pio_nowrite) + + ! Read in input mesh + mesh_i = ESMF_MeshCreate(filename=trim(file_mesh_i), fileformat=ESMF_FILEFORMAT_ESMFMESH, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After create mesh_i in "//trim(subname)) + + ! Determine ns_i + call ESMF_MeshGet(mesh_i, numOwnedElements=ns_i, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Determine ns_o and allocate output data + call ESMF_MeshGet(mesh_o, numOwnedElements=ns_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + allocate (gdp_o(ns_o)); gdp_o(:) = spval + + ! Get the landmask from the file and reset the mesh mask based on that + allocate(frac_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort() + allocate(mask_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort() + call mkpio_get_rawdata(pioid_i, 'LANDMASK', mesh_i, frac_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + do ni = 1,ns_i + if (frac_i(ni) > 0._r4) then + mask_i(ni) = 1 + else + mask_i(ni) = 0 + end if + end do + call ESMF_MeshSet(mesh_i, elementMask=mask_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! Read in gdp_i + allocate(gdp_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort() + call mkpio_get_rawdata(pioid_i, 'gdp', mesh_i, gdp_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After mkpio_getrawdata in "//trim(subname)) + + ! Create a route handle between the input and output mesh and get frac_o + allocate(frac_o(ns_o),stat=ier) + if (ier/=0) call shr_sys_abort() + call create_routehandle_r8(mesh_i=mesh_i, mesh_o=mesh_o, norm_by_fracs=.true., & + routehandle=routehandle, frac_o=frac_o, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After create routehandle in "//trim(subname)) + + ! Regrid gdp + call regrid_rawdata(mesh_i, mesh_o, routehandle, gdp_i, gdp_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + if (min_bad(gdp_o, min_valid, 'gdp')) then + call shr_sys_abort(subname//' error in reading gdp_i') + end if + + ! Close the file + call pio_closefile(pioid_i) + + ! Write output data + if (root_task) write(ndiag, '(a)') trim(subname)//" writing out gdp" + call mkfile_output(pioid_o, mesh_o, 'gdp', gdp_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkfile_output') + call pio_syncfile(pioid_o) + + ! Output diagnostic info + call output_diagnostics_continuous(mesh_i, mesh_o, gdp_i, gdp_o, & + "GDP", "x1000 US$ per capita", ndiag=ndiag, rc=rc, mask_i=mask_i, frac_o=frac_o) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + + ! Clean up memory + call ESMF_RouteHandleDestroy(routehandle, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + call ESMF_MeshDestroy(mesh_i, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + + if (root_task) then + write (ndiag,'(a)') 'Successfully made GDP' + end if + call ESMF_VMLogMemInfo("At end of "//trim(subname)) + + end subroutine mkgdp + +end module mkgdpMod diff --git a/tools/mksurfdata_esmf/src/mkglacierregionMod.F90 b/tools/mksurfdata_esmf/src/mkglacierregionMod.F90 new file mode 100644 index 0000000000..267e46ddfa --- /dev/null +++ b/tools/mksurfdata_esmf/src/mkglacierregionMod.F90 @@ -0,0 +1,176 @@ +module mkglacierregionMod + + !----------------------------------------------------------------------- + ! make glacier region ID + ! Regridding is done by finding the nearest neighbor source cell for each destination cell. + !----------------------------------------------------------------------- + + use ESMF + use shr_kind_mod , only : r8 => shr_kind_r8, r4=>shr_kind_r4 + use shr_sys_mod , only : shr_sys_abort + use pio , only : file_desc_t, pio_openfile, pio_closefile, pio_nowrite + use mkpioMod , only : mkpio_get_rawdata, pio_iotype, pio_iosystem + use mkesmfMod , only : regrid_rawdata, create_routehandle_r8 + use mkchecksMod , only : min_bad + use mkvarctl , only : ndiag, root_task + use mkdiagnosticsMod , only : output_diagnostics_index + use mkutilsMod , only : chkerr + use mkfileMod , only : mkfile_output + + implicit none + private + + public :: mkglacierregion ! make glacier region ID + + integer, private :: nglacier_regions = 3 + + character(len=*) , parameter :: u_FILE_u = & + __FILE__ + +!================================================================================= +contains +!================================================================================= + + subroutine mkglacierregion(file_mesh_i, file_data_i, mesh_o, pioid_o, rc) + ! + ! Make glacier region ID + ! + ! input/output variables + character(len=*) , intent(in) :: file_mesh_i ! input mesh file name + character(len=*) , intent(in) :: file_data_i ! input data file name + type(ESMF_Mesh) , intent(in) :: mesh_o ! output mesh + type(file_desc_t) , intent(inout) :: pioid_o + integer , intent(out) :: rc + + ! local variables: + type(ESMF_RouteHandle) :: routehandle ! nearest neighbor routehandle + type(ESMF_Mesh) :: mesh_i + type(file_desc_t) :: pioid_i + integer :: ni,no,l,k + integer :: ns_i, ns_o + integer , allocatable :: mask_i(:) + real(r8), allocatable :: frac_i(:) + real(r8), allocatable :: frac_o(:) + real(r8), allocatable :: data_i(:,:) + real(r8), allocatable :: data_o(:,:) + integer , allocatable :: glacier_region_i(:) ! glacier region on input grid + integer , allocatable :: glacier_region_o(:) ! glacier region on output grid + integer :: ier, rcode ! error status + integer :: max_index(1) + character(len=*), parameter :: subname = 'mkglacierregion' + !----------------------------------------------------------------------- + + rc = ESMF_SUCCESS + + if (root_task) then + write(ndiag,*) + write(ndiag,'(1x,80a1)') ('=',k=1,80) + write(ndiag,*) + write(ndiag,'(a)') 'Attempting to make glacier region .....' + write(ndiag,'(a)') ' Input file is '//trim(file_data_i) + write(ndiag,'(a)') ' Input mesh file is '//trim(file_mesh_i) + end if + call ESMF_VMLogMemInfo("At start of "//trim(subname)) + + ! Open input data file + rcode = pio_openfile(pio_iosystem, pioid_i, pio_iotype, trim(file_data_i), pio_nowrite) + + ! Read in input mesh + mesh_i = ESMF_MeshCreate(filename=trim(file_mesh_i), fileformat=ESMF_FILEFORMAT_ESMFMESH, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After create mesh_i in "//trim(subname)) + + ! Determine ns_i + call ESMF_MeshGet(mesh_i, numOwnedElements=ns_i, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Determine ns_o and allocate output data + call ESMF_MeshGet(mesh_o, numOwnedElements=ns_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + allocate (glacier_region_o(ns_o)) ; glacier_region_o(:) = -999 + + ! Read in input data (Confirm that no value of glacier_region is less than min_allowed) + allocate(glacier_region_i(ns_i), stat=ier) + if (ier/=0) call abort() + call mkpio_get_rawdata(pioid_i, 'GLACIER_REGION', mesh_i, glacier_region_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + if (min_bad(glacier_region_i, 0, 'GLACIER_REGION')) then + call shr_sys_abort() + end if + call ESMF_VMLogMemInfo("After mkpio_getrawdata in "//trim(subname)) + + ! Reset mesh mask to zero where glacier_region_i is zero + allocate(frac_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort() + allocate(mask_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort() + do ni = 1,ns_i + if (glacier_region_i(ni) == 0) then + mask_i(ni) = 0 + else + mask_i(ni) = 1 + end if + end do + call ESMF_MeshSet(mesh_i, elementMask=mask_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! Create a route handle between the input and output mesh + allocate(frac_o(ns_o)) + if (ier/=0) call abort() + call create_routehandle_r8(mesh_i=mesh_i, mesh_o=mesh_o, norm_by_fracs=.true., & + routehandle=routehandle, frac_o=frac_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After create routehandle in "//trim(subname)) + + ! Now determine data_i as a real 2d array - for every possible glacier region create a global + ! field with gridcells equal to 1 for that region and zero elsewhere + allocate(data_i(0:nglacier_regions,ns_i)) + data_i(:,:) = 0._r4 + do l = 0,nglacier_regions + do ni = 1,ns_i + if (glacier_region_i(ni) == l) then + data_i(l,ni) = 1._r4 + end if + end do + end do + + ! Regrid data_i to data_o + allocate(data_o(0:nglacier_regions, ns_o), stat=ier) + if (ier/=0) call shr_sys_abort('error allocating data_i(max_regions, ns_o)') + call regrid_rawdata(mesh_i, mesh_o, routehandle, data_i, data_o, 0, nglacier_regions, rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Determine glacier_region_o + glacier_region_o(:) = 0 + do no = 1,ns_o + max_index = maxloc(data_o(:,no)) + glacier_region_o(no) = max_index(1) - 1 + end do + + ! Write output data + if (root_task) write(ndiag, '(a)') trim(subname)//" writing out glacier_region" + call mkfile_output(pioid_o, mesh_o, 'GLACIER_REGION', glacier_region_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkfile_output') + + ! Determine global diagnostics + call output_diagnostics_index(mesh_i, mesh_o, mask_i, frac_o, & + 0, 3, glacier_region_i, glacier_region_o, 'Glacier Region ID', ndiag, rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + + ! Close the input file + call pio_closefile(pioid_i) + + ! Release memory + call ESMF_RouteHandleDestroy(routehandle, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + call ESMF_MeshDestroy(mesh_i, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + + if (root_task) then + write (ndiag,'(a)') 'Successfully made glacier region' + end if + call ESMF_VMLogMemInfo("At end of "//trim(subname)) + + end subroutine mkglacierregion + +end module mkglacierregionMod diff --git a/tools/mksurfdata_esmf/src/mkglcmecMod.F90 b/tools/mksurfdata_esmf/src/mkglcmecMod.F90 new file mode 100644 index 0000000000..25fa4a8edc --- /dev/null +++ b/tools/mksurfdata_esmf/src/mkglcmecMod.F90 @@ -0,0 +1,719 @@ +module mkglcmecMod + + !----------------------------------------------------------------------- + ! Make glacier multi-elevation class data + !----------------------------------------------------------------------- + + use ESMF + use shr_kind_mod , only : r8 => shr_kind_r8, r4=>shr_kind_r4 + use shr_sys_mod , only : shr_sys_abort + use pio , only : file_desc_t, pio_openfile, pio_closefile, pio_nowrite + use pio , only : var_desc_t, io_desc_t, Pio_Offset_Kind, pio_setframe + use pio , only : pio_inq_dimid, pio_inq_dimlen, pio_inq_varid + use pio , only : pio_put_var, pio_get_var + use mkpioMod , only : mkpio_get_rawdata, pio_iotype, pio_iosystem + use mkpioMod , only : mkpio_iodesc_rawdata, mkpio_get_rawdata_level + use mkesmfMod , only : regrid_rawdata, create_routehandle_r8 + use mkvarctl , only : ndiag, root_task, outnc_3dglc, spval, nglcec + use mkutilsMod , only : chkerr + use mkutilsMod , only : slightly_below, slightly_above + use mkfileMod , only : mkfile_output + use mkdiagnosticsMod , only : output_diagnostics_area + + implicit none + private ! By default make data private + + public :: mkglcmecInit ! Initialization + public :: mkglcmec ! Set glacier multi-elevation class + public :: mkglacier ! Set percent glacier + + private :: get_elevclass ! get elevation class index + private :: mean_elevation_vc ! get the elevation of a virtual column + + real(r8), allocatable :: elevclass(:) ! elevation classes + + character(len=*) , parameter :: u_FILE_u = & + __FILE__ + +!================================================================================= +contains +!================================================================================= + + subroutine mkglcmecInit( pioid_o ) + ! + ! Initialize of Make glacier multi-elevation class data + ! + ! input/output variables + type(file_desc_t) , intent(inout) :: pioid_o + + ! local variables: + type(var_desc_t) :: pio_varid + type(io_desc_t) :: pio_iodesc + real(r8), allocatable :: elevclass_o(:) ! elevation classes + integer :: rcode + character(len=*), parameter :: subname = 'mkglcmecInit' + !----------------------------------------------------------------------- + + allocate( elevclass(nglcec+1) ) + + ! Define elevation classes, represents lower boundary of each class + + if ( nglcec == 36 )then + elevclass(:) = (/ 0., 200., 400., 600., 800., & + 1000., 1200., 1400., 1600., 1800., & + 2000., 2200., 2400., 2600., 2800., & + 3000., 3200., 3400., 3600., 3800., & + 4000., 4200., 4400., 4600., 4800., & + 5000., 5200., 5400., 5600., 5800., & + 6000., 6200., 6400., 6600., 6800., & + 7000., 10000./) + else if ( nglcec == 10 )then + elevclass(1) = 0. + elevclass(2) = 200. + elevclass(3) = 400. + elevclass(4) = 700. + elevclass(5) = 1000. + elevclass(6) = 1300. + elevclass(7) = 1600. + elevclass(8) = 2000. + elevclass(9) = 2500. + elevclass(10) = 3000. + elevclass(11) = 10000. + else if ( nglcec == 5 )then + elevclass(1) = 0. + elevclass(2) = 500. + elevclass(3) = 1000. + elevclass(4) = 1500. + elevclass(5) = 2000. + elevclass(6) = 10000. + else if ( nglcec == 3 )then + elevclass(1) = 0. + elevclass(2) = 1000. + elevclass(3) = 2000. + elevclass(4) = 10000. + else if ( nglcec == 1 )then + elevclass(1) = 0. + elevclass(2) = 10000. + else + write(6,*) subname//"error:: nglcec must be 1, 3, 5, 10 or 36",& + " to work with CLM: " + call shr_sys_abort() + end if + + elevclass_o(:) = elevclass(:) + + if (root_task) write(ndiag, '(a)') trim(subname)//" writing out GLC_MEC" + rcode = pio_inq_varid(pioid_o, 'GLC_MEC', pio_varid) + rcode = pio_put_var(pioid_o, pio_varid, elevclass) + + end subroutine mkglcmecInit + + !================================================================================= + subroutine mkglcmec(file_mesh_i, file_data_i, mesh_o, pioid_o, rc) + ! + ! make percent glacier on multiple elevation classes, mean elevation for each + ! elevation class, and associated fields + ! + ! Note that the raw glacier data are specified by level, and thus implicitly include the + ! necessary topo data for breaking pct glacier into elevation classes. Each level in the + ! input data is assigned to an elevation (given by BIN_CENTERS in the input data). Thus, + ! all of the input glacier in level 1 is treated as being at the same elevation, and + ! likewise for each other level. These elevations are then used in assigning pct_glacier + ! to the appropriate elevation class in the output data, as well as determining the mean + ! topographic height of each elevation class in the output data. + ! + ! Note that the various percentages computed here are given as % of the glc_mec landunit. + ! If the input glacier area is 0 for a given grid cell, this requires setting these % + ! variables in an arbitrary way. + ! + ! input/output variables + character(len=*) , intent(in) :: file_mesh_i ! input mesh file name + character(len=*) , intent(in) :: file_data_i ! input data file name + type(ESMF_Mesh) , intent(in) :: mesh_o ! output mesh + type(file_desc_t) , intent(inout) :: pioid_o + integer , intent(out) :: rc + + ! local variables: + type(ESMF_RouteHandle) :: routehandle_nonorm + type(ESMF_Mesh) :: mesh_i + type(file_desc_t) :: pioid_i + type(var_desc_t) :: pio_varid + type(io_desc_t) :: pio_iodesc + integer :: pio_vartype + integer :: ni,no,lev + integer :: ns_i, ns_o + integer :: n,m,k ! indices + integer :: dimid ! dimension ids + integer :: ndims ! number of dimensions in input variables + integer :: nlev ! number of levels in input file + integer , allocatable :: mask_i(:) + real(r8), allocatable :: frac_i(:) + real(r8), allocatable :: frac_o_nonorm(:) + real(r8), allocatable :: area_i(:) + real(r8), allocatable :: area_o(:) + real(r8), allocatable :: data_pctglc_i(:) + real(r8), allocatable :: data_pctglc_o(:) + real(r8), allocatable :: data_pctglc_icesheet_i(:) ! input icesheet percentage + real(r8), allocatable :: data_pctglc_icesheet_o(:) ! input icesheet percentage + real(r8), allocatable :: data_pctglc_gic_i(:) + real(r8), allocatable :: data_pctglc_gic_o(:) + real(r8), allocatable :: topoglcmec_unnorm_o(:,:) ! same as topoglcmec_o, but unnormalized + real(r8), allocatable :: pctglc_tot_o(:) ! total glacier cover for the grid cell + real(r4), allocatable :: topoice_i(:) ! topographic height of this level + real(r8), allocatable :: pctglcmec_o (:,:) ! % for each elevation class on output glacier grid (% of landunit) + real(r8), allocatable :: topoglcmec_o(:,:) ! mean elevation for each elevation classs on output glacier grid + real(r8), allocatable :: pctglcmec_gic_o(:,:) ! % glc gic on output grid, by elevation class (% of landunit) + real(r8), allocatable :: pctglcmec_icesheet_o(:,:) ! % glc ice sheet on output grid, by elevation class (% of landunit) + real(r8), allocatable :: pctglc_gic_o(:) ! % glc gic on output grid, summed across elevation classes (% of landunit) + real(r8), allocatable :: pctglc_icesheet_o(:) ! % glc ice sheet on output grid, summed across elevation classes (% of landunit) + integer :: unlimited_index ! z level + real(r8) :: glc_sum ! temporary + integer :: ier, rcode ! error status + logical :: errors ! error status + real(r8), parameter :: eps = 2.e-5_r8 ! epsilon for error checks (note that we use a large-ish value + ! because data are stored as single-precision floats in the raw dataset) + real(r8), parameter :: eps_small = 1.e-12_r8 ! epsilon for error checks that expect close match + character(len=*), parameter :: subname = 'mkglcmec' + !----------------------------------------------------------------------- + + rc = ESMF_SUCCESS + + if (root_task) then + write(ndiag,*) + write(ndiag,'(1x,80a1)') ('=',k=1,80) + write(ndiag,*) + write(ndiag,'(a)') 'Attempting to make percent elevation class ',& + 'and mean elevation for glaciers .....' + write(ndiag,'(a)') ' Input file is '//trim(file_data_i) + write(ndiag,'(a)') ' Input mesh file is '//trim(file_mesh_i) + end if + + ! Open input data file + call ESMF_VMLogMemInfo("Before pio_openfile for "//trim(file_data_i)) + rcode = pio_openfile(pio_iosystem, pioid_i, pio_iotype, trim(file_data_i), pio_nowrite) + call ESMF_VMLogMemInfo("After pio_openfile "//trim(file_data_i)) + + ! Read in input mesh + call ESMF_VMLogMemInfo("Before create mesh_i in "//trim(subname)) + mesh_i = ESMF_MeshCreate(filename=trim(file_mesh_i), fileformat=ESMF_FILEFORMAT_ESMFMESH, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After create mesh_i in "//trim(subname)) + + ! Determine ns_i + call ESMF_MeshGet(mesh_i, numOwnedElements=ns_i, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Determine ns_o and allocate output data + call ESMF_MeshGet(mesh_o, numOwnedElements=ns_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + allocate(pctglcmec_o(ns_o,nglcec)) + pctglcmec_o(:,:) = 0. + + allocate(topoglcmec_o(ns_o,nglcec)) + topoglcmec_o(:,:) = 0. + if ( outnc_3dglc )then + allocate(pctglcmec_gic_o(ns_o,nglcec)) + pctglcmec_gic_o(:,:) = 0. + + allocate(pctglcmec_icesheet_o(ns_o,nglcec)) + pctglcmec_icesheet_o(:,:) = 0. + + allocate(pctglc_gic_o(ns_o)) + pctglc_gic_o(:) = 0. + + allocate(pctglc_icesheet_o(ns_o)) + pctglc_icesheet_o(:) = 0. + end if + + ! Get the landmask from the file and reset the mesh mask based on that + allocate(frac_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort(subname//" error in allocating frac_i") + allocate(mask_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort(subname//" error in allocating mask_i") + call mkpio_get_rawdata(pioid_i, 'LANDMASK', mesh_i, frac_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + do ni = 1,ns_i + if (frac_i(ni) > 0._r8) then + mask_i(ni) = 1 + else + mask_i(ni) = 0 + end if + end do + call ESMF_MeshSet(mesh_i, elementMask=mask_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! Read in BIN_CENTERS on all tasks and check validity + rcode = pio_inq_dimid (pioid_i, 'z', dimid) + rcode = pio_inq_dimlen(pioid_i, dimid, nlev) + ! TODO: hard-wiring topoice to be r4 - this needs to be generalized to query the variable type + ! on the netcdf file + allocate(topoice_i(nlev)) + rcode = pio_inq_varid (pioid_i, 'BIN_CENTERS', pio_varid) + rcode = pio_get_var(pioid_i, pio_varid, topoice_i) + do lev = 1,nlev + m = get_elevclass(topoice_i(lev)) + if (m < 1 .or. m > nglcec) then + call shr_sys_abort(subname//" error m<1 or m > nglcec") + end if + end do + + ! Allocate memory for reading in one level at a time + allocate(data_pctglc_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort(subname//" error in allocating data_pctglc_i") + allocate(data_pctglc_o(ns_o), stat=ier) + if (ier/=0) call shr_sys_abort(subname//" error in allocating data_pctglc_o") + + allocate(data_pctglc_gic_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort(subname//" error in allocating data_pctglc_gic_i") + allocate(data_pctglc_gic_o(ns_o), stat=ier) + if (ier/=0) call shr_sys_abort(subname//" error in allocating data_pctglc_gic_o") + + allocate(data_pctglc_icesheet_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort(subname//" error in allocating data_pctglc_icesheet_i") + allocate(data_pctglc_icesheet_o(ns_o), stat=ier) + if (ier/=0) call shr_sys_abort(subname//" error in allocating data_pctglc_icesheet_o") + + allocate(topoglcmec_unnorm_o(ns_o,nglcec), stat=ier) + if (ier/=0) call shr_sys_abort(subname//" error in allocating topoglcmec_unnorm_o") + topoglcmec_unnorm_o(:,:) = 0. + + ! Create iodescriptor for a single level of the input data + call mkpio_iodesc_rawdata(mesh_i, 'PCT_GLC_GIC', pioid_i, pio_varid, pio_vartype, pio_iodesc, rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! Create a route handle between the input and output mesh and get frac_o_nonorm + allocate(frac_o_nonorm(ns_o),stat=ier) + if (ier/=0) call shr_sys_abort(subname//" error in allocating frac_o_nonorm") + ! Note that norm_by_fracs is false in the following because this routehandle is + ! used to map fields that are expressed in terms of % of the grid cell. + call create_routehandle_r8(mesh_i=mesh_i, mesh_o=mesh_o, norm_by_fracs=.false., & + routehandle=routehandle_nonorm, frac_o=frac_o_nonorm, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After create routehandle in "//trim(subname)) + + ! Compute pctglcmec_gic_o, pctglcmec_gic_o, pctglcmec_icesheet_o and topoglcmec_unnorm_o + ! Note that topoglcmec_unnorm_o is the average topographic height over glaciated areas - + ! NOT the average topographic height of the entire grid cell + do lev = 1, nlev + write(6,'(i4)',advance='no') lev + + ! Read in one level of data + rcode = pio_inq_varid(pioid_i, 'PCT_GLC_GIC', pio_varid) + call pio_setframe(pioid_i, pio_varid, int(lev,kind=Pio_Offset_Kind)) + call mkpio_get_rawdata_level(pioid_i, pio_iodesc, lev, 'PCT_GLC_GIC', data_pctglc_gic_i) + + rcode = pio_inq_varid(pioid_i, 'PCT_GLC_ICESHEET', pio_varid) + call pio_setframe(pioid_i, pio_varid, int(lev,kind=Pio_Offset_Kind)) + call mkpio_get_rawdata_level(pioid_i, pio_iodesc, lev, 'PCT_GLC_ICESHEET', data_pctglc_icesheet_i) + + ! Compute derived input data + data_pctglc_i(:) = data_pctglc_gic_i(:) + data_pctglc_icesheet_i(:) + + ! Map level of data to output grid + call regrid_rawdata(mesh_i, mesh_o, routehandle_nonorm, data_pctglc_i, data_pctglc_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call regrid_rawdata(mesh_i, mesh_o, routehandle_nonorm, data_pctglc_gic_i, data_pctglc_gic_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call regrid_rawdata(mesh_i, mesh_o, routehandle_nonorm, data_pctglc_icesheet_i, data_pctglc_icesheet_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Compute output variables + m = get_elevclass(topoice_i(lev)) + do no = 1,ns_o + pctglcmec_o(no,m) = pctglcmec_o(no,m) + data_pctglc_o(no) + if (outnc_3dglc) then + pctglcmec_gic_o(no,m) = pctglcmec_gic_o(no,m) + data_pctglc_gic_o(no) + pctglcmec_icesheet_o(no,m) = pctglcmec_icesheet_o(no,m) + data_pctglc_icesheet_o(no) + end if + topoglcmec_unnorm_o(no,m) = topoglcmec_unnorm_o(no,m) + data_pctglc_o(no)*topoice_i(lev) + end do + end do + + ! Close glacier input file + call pio_closefile(pioid_i) + call ESMF_VMLogMemInfo("After pio_closefile in "//trim(subname)) + + ! At this point, the various percentages are given as % of grid cell. + ! We now renormalize these to be given as % of landunit. + + ! Normalize topoglcmec_o. To do this, note that pctglcmec_o(n,m) is equal to the sum of + ! the weights used in doing the weighted average of topoice_i (weight = wt*pctglc_i/frac); + ! hence pctglcmec_o(n,m) is the correct normalization factor + do no = 1,ns_o + do m = 1,nglcec + if (pctglcmec_o(no,m) > 0) then + topoglcmec_o(no,m) = topoglcmec_unnorm_o(no,m) / pctglcmec_o(no,m) + else + topoglcmec_o(no,m) = mean_elevation_vc(m) + end if + + ! Correct for rounding errors that put topoglcmec_o(no,m) slightly outside the + ! allowed bounds for this elevation class + if (slightly_below(topoglcmec_o(no,m), elevclass(m))) then + write(6,*) 'Warning: topoglcmec_o was slightly lower than lower bound; setting equal& + & to lower bound; for: ', no, m, topoglcmec_o(no,m), elevclass(m) + write(6,*) '(this is informational only, and probably just indicates rounding error)' + topoglcmec_o(no,m) = elevclass(m) + else if (slightly_above(topoglcmec_o(no,m), elevclass(m+1))) then + write(6,*) 'Warning: topoglcmec_o was slightly higher than upper bound; setting equal& + & to upper bound; for: ', no, m, topoglcmec_o(no,m), elevclass(m+1) + write(6,*) '(this is informational only, and probably just indicates rounding error)' + topoglcmec_o(no,m) = elevclass(m+1) + end if + end do + end do + + ! Renormalize percentages to be given as % of landunit rather than % of grid cell. + allocate(pctglc_tot_o(ns_o), stat=ier) + if (ier/=0) call shr_sys_abort(subname//" error in allocating pctglc_tot") + do no = 1,ns_o + pctglc_tot_o(no) = sum(pctglcmec_o(no,:)) + if (pctglc_tot_o(no) > 0._r8) then + pctglcmec_o(no,:) = pctglcmec_o(no,:) / pctglc_tot_o(no) * 100._r8 + if ( outnc_3dglc )then + pctglcmec_gic_o(no,:) = pctglcmec_gic_o(no,:) / pctglc_tot_o(no) * 100._r8 + pctglcmec_icesheet_o(no,:) = pctglcmec_icesheet_o(no,:) / pctglc_tot_o(no) * 100._r8 + end if + else + ! Division of landunit is ambiguous. Apply the rule that all area is assigned to + ! the lowest elevation class, and all GIC. + pctglcmec_o(no,1) = 100._r8 + if ( outnc_3dglc ) then + pctglcmec_gic_o(no,1) = 100._r8 + end if + end if + end do + + ! Set pctglc_gic_o to sum of pctglcmec_gic_o across elevation classes, and similarly for pctglc_icesheet_o + if ( outnc_3dglc )then + pctglc_gic_o = sum(pctglcmec_gic_o, dim=2) + pctglc_icesheet_o = sum(pctglcmec_icesheet_o, dim=2) + end if + + ! -------------------------------------------------------------------- + ! Perform various sanity checks + ! -------------------------------------------------------------------- + + ! Confirm that the sum over pctglcmec_o (from 1 to nglcec) is 100% + errors = .false. + do no = 1,ns_o + glc_sum = sum(pctglcmec_o(no,:)) + if (abs(glc_sum - 100._r8) > eps_small) then + write(6,*)'glc_sum differs from 100% at no,pctglc= ',no,glc_sum + errors = .true. + end if + end do + + ! Confirm that GIC + ICESHEET = 100% + if ( outnc_3dglc )then + do no = 1,ns_o + if (abs((pctglc_gic_o(no) + pctglc_icesheet_o(no)) - 100._r8) > eps) then + write(6,*)'GIC + ICESHEET differs from 100% at no,pctglc_gic,pctglc_icesheet =', & + no,pctglc_gic_o(no),pctglc_icesheet_o(no) + errors = .true. + ! TODO: output lat and lon out above + end if + end do + + ! Check that GIC + ICESHEET = total glacier at each elevation class + do m = 1, nglcec + do no = 1,ns_o + if (abs((pctglcmec_gic_o(no,m) + pctglcmec_icesheet_o(no,m)) - & + pctglcmec_o(no,m)) > eps) then + write(6,*)'GIC + ICESHEET differs from total GLC ' + write(6,*)'at no,m,pctglcmec,pctglcmec_gic,pctglcmec_icesheet = ' + write(6,*) no,m,pctglcmec_o(no,m),pctglcmec_gic_o(no,m),pctglcmec_icesheet_o(no,m) + errors = .true. + end if + end do + end do + end if + + ! Error check: are all elevations within elevation class range + do no = 1,ns_o + do m = 1,nglcec + if (topoglcmec_o(no,m) < elevclass(m) .or. topoglcmec_o(no,m) > elevclass(m+1)) then + write(6,*) 'Error: mean elevation does not fall within elevation class ' + write(6,*) elevclass(m),elevclass(m+1),topoglcmec_o(no,m),m,no + errors = .true. + endif + end do + end do + + if (errors) then + call shr_sys_abort(subname//" error in error checks") + end if + + ! Output data tp fo;e + if (root_task) write(ndiag, '(a)') trim(subname)//" writing out pct_glc_mec" + call mkfile_output(pioid_o, mesh_o, 'PCT_GLC_MEC', pctglcmec_o, lev1name='nglcec', rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkfile_output') + + if (root_task) write(ndiag, '(a)') trim(subname)//" writing out topo_glc_mec" + call mkfile_output(pioid_o, mesh_o, 'TOPO_GLC_MEC', topoglcmec_o, lev1name='nglcec', rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkfile_output') + + if (outnc_3dglc ) then + if (root_task) write(ndiag, '(a)') trim(subname)//" writing out pct_glc_mec_gic" + call mkfile_output(pioid_o, mesh_o, 'PCT_GLC_MEC_GIC', pctglcmec_gic_o, lev1name='nglcec', rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkfile_output') + + if (root_task) write(ndiag, '(a)') trim(subname)//" writing out pct_glc_mec_icesheet" + call mkfile_output(pioid_o, mesh_o, 'PCT_GLC_MEC_ICESHEET', pctglcmec_icesheet_o, lev1name='nglcec', rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkfile_output') + + if (root_task) write(ndiag, '(a)') trim(subname)//" writing out pct_glc_gic" + call mkfile_output(pioid_o, mesh_o, 'PCT_GLC_GIC', pctglc_gic_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkfile_output') + + if (root_task) write(ndiag, '(a)') trim(subname)//" writing out pct_icesheet" + call mkfile_output(pioid_o, mesh_o, 'PCT_GLC_ICESHEET', pctglc_icesheet_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkfile_output') + end if + + ! Deallocate dynamic memory + call ESMF_RouteHandleDestroy(routehandle_nonorm, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + call ESMF_MeshDestroy(mesh_i, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + call ESMF_VMLogMemInfo("After destroy operations in "//trim(subname)) + + if (root_task) then + write (ndiag,'(a)') 'Successfully made percent elevation class and mean elevation for glaciers' + end if + + end subroutine mkglcmec + + !================================================================================= + subroutine mkglacier(file_mesh_i, file_data_i, mesh_o, glac_o, rc) + ! + ! make percent glacier + ! + ! In contrast to mkglcmec, this uses a "flat" PCT_GLACIER field (not separated by + ! elevation class, and not separated into icesheet vs GIC). + ! + ! This simpler routine is sufficient for cases when we run without multiple elevation + ! classes. This routine is also used when running with multiple elevation classes: we + ! first regrid the flat PCT_GLACIER field, then later create the multiple elevation class + ! data. This multi-step process makes it easier to do corrections on the total + ! PCT_GLACIER, and make sure these corrections apply appropriately to the multi-level + ! output. The assumption is that PCT_GLACIER is the sum of both PCT_GLC_GIC and + ! PCT_GLC_ICESHEET across all elevation bins. + ! + ! input/output variables + character(len=*) , intent(in) :: file_mesh_i ! input mesh file name + character(len=*) , intent(in) :: file_data_i ! input data file name + type(ESMF_Mesh) , intent(in) :: mesh_o ! output mesh + real(r8) , intent(out) :: glac_o(:) ! output grid: %glacier + integer , intent(out) :: rc + ! + ! local variables + type(ESMF_RouteHandle) :: routehandle_nonorm + type(ESMF_Mesh) :: mesh_i + type(file_desc_t) :: pioid + integer :: ni,no,k + integer :: ns_i, ns_o + integer , allocatable :: mask_i(:) + real(r8), allocatable :: frac_i(:) + real(r8), allocatable :: frac_o_nonorm(:) + real(r8), allocatable :: area_i(:) + real(r8), allocatable :: area_o(:) + real(r8), allocatable :: glac_i(:) ! input grid: percent glac + real(r8) :: sum_fldi ! global sum of dummy input fld + real(r8) :: sum_fldo ! global sum of dummy output fld + real(r8) :: gglac_i ! input grid: global glac + real(r8) :: garea_i ! input grid: global area + real(r8) :: gglac_o ! output grid: global glac + real(r8) :: garea_o ! output grid: global area + integer :: ier, rcode ! error status + real(r8) :: relerr = 0.00001 ! max error: sum overlap wts ne 1 + character(len=*), parameter :: subname = 'mkglacier' + !----------------------------------------------------------------------- + + if (root_task) then + write(ndiag,*) + write(ndiag,'(1x,80a1)') ('=',k=1,80) + write(ndiag,*) + write(ndiag,'(a)') 'Attempting to make %glacier .....' + write(ndiag,'(a)') ' Input file is '//trim(file_data_i) + write(ndiag,'(a)') ' Input mesh file is '//trim(file_mesh_i) + end if + + ! Open input data file + rcode = pio_openfile(pio_iosystem, pioid, pio_iotype, trim(file_data_i), pio_nowrite) + call ESMF_VMLogMemInfo("After pio_openfile "//trim(file_data_i)) + + ! Read in input mesh + mesh_i = ESMF_MeshCreate(filename=trim(file_mesh_i), fileformat=ESMF_FILEFORMAT_ESMFMESH, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After create mesh_i in "//trim(subname)) + + ! Determine ns_i + call ESMF_MeshGet(mesh_i, numOwnedElements=ns_i, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Determine ns_o + call ESMF_MeshGet(mesh_o, numOwnedElements=ns_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Get the landmask from the file and reset the mesh mask based on that + allocate(frac_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort(subname//" ERROR in allocating frac_i") + allocate(mask_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort(subname//" ERROR in allocating mask_i") + call mkpio_get_rawdata(pioid, 'LANDMASK', mesh_i, frac_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + do ni = 1,ns_i + if (frac_i(ni) > 0._r4) then + mask_i(ni) = 1 + else + mask_i(ni) = 0 + end if + end do + call ESMF_MeshSet(mesh_i, elementMask=mask_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! Read in glac_i + allocate(glac_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort(subname//" error in allocating glac_i") + call mkpio_get_rawdata(pioid, 'PCT_GLACIER', mesh_i, glac_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After mkpio_getrawdata in "//trim(subname)) + + ! Create a route handle between the input and output mesh and get frac_o_nonorm + allocate(frac_o_nonorm(ns_o),stat=ier) + if (ier/=0) call shr_sys_abort() + ! Note that norm_by_fracs is false in the following because this routehandle is + ! used to map fields that are expressed in terms of % of the grid cell. + call create_routehandle_r8(mesh_i=mesh_i, mesh_o=mesh_o, norm_by_fracs=.false., & + routehandle=routehandle_nonorm, frac_o=frac_o_nonorm, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After create routehandle in "//trim(subname)) + + ! Area-average percent cover on input grid to output grid (with correction for landmask) + ! Note that percent cover is in terms of total grid area. + ! Regrid glac_i to glac_o + call regrid_rawdata(mesh_i, mesh_o, routehandle_nonorm, glac_i, glac_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + do no = 1,ns_o + if (glac_o(no) < 1._r8) then + glac_o(no) = 0._r8 + else if ((glac_o(no)) > 101._r8) then + write(6,*) 'MKGLACIER error: glacier = ', glac_o(no), & + ' > 101 for no = ', no + call shr_sys_abort() + else if ((glac_o(no)) > 100._r8) then + if ((glac_o(no)) > 100.000001_r8) then + write(6,*) 'MKGLACIER warning: glacier = ', glac_o(no), & + ' > 100.000001 for no = ', no, ' Changing glacier > 100 to 100.' + end if + glac_o(no) = 100._r8 + end if + enddo + + ! Check global areas + call output_diagnostics_area(mesh_i, mesh_o, mask_i, frac_o_nonorm, & + glac_i, glac_o, "pct glacier", percent=.true., ndiag=ndiag, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Deallocate dynamic memory + deallocate (glac_i, frac_o_nonorm, mask_i) + call ESMF_RouteHandleDestroy(routehandle_nonorm, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + call ESMF_MeshDestroy(mesh_i, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + + if (root_task) then + write (ndiag,'(a)') 'Successfully made %glacier' + end if + + end subroutine mkglacier + + !================================================================================= + integer function get_elevclass(topo, writewarn) + ! + ! Returns elevation class index (1..nglcec) given the topographic height. + ! If topo is lower than the lowest elevation class, returns 0. + ! If topo is higher than the highest elevation class, returns (nglcec+1). + ! In either of the two latter cases, the function also writes a warning message, unless + ! writewarn is present and false. + ! + ! input/output variables + real(r4), intent(in) :: topo ! topographic height (m) + logical, intent(in), optional :: writewarn ! should warning messages be written? (default: true) + ! + ! local variables + integer :: m + logical :: my_writewarn + character(len=*), parameter :: subname = 'get_elevclass' + !----------------------------------------------------------------------- + + if (present(writewarn)) then + my_writewarn = writewarn + else + my_writewarn = .true. + end if + + if (topo < elevclass(1)) then + if (my_writewarn) then + write(6,*) 'WARNING in ', trim(subname) + write(6,*) 'topo out of bounds' + write(6,*) 'topo = ', topo + write(6,*) 'elevclass(1) = ', elevclass(1) + end if + get_elevclass = 0 + return + end if + + do m = 1, nglcec + if (topo < elevclass(m+1)) then + ! note that we already know that topo >= elevclass(m), otherwise we would have + ! returned earlier + get_elevclass = m + return + end if + end do + + if (my_writewarn) then + write(6,*) 'WARNING in ', trim(subname) + write(6,*) 'topo out of bounds' + write(6,*) 'topo = ', topo + write(6,*) 'elevclass(nglcec+1) = ', elevclass(nglcec+1) + end if + get_elevclass = nglcec+1 + + end function get_elevclass + + !================================================================================= + real(r8) function mean_elevation_vc(class) + ! + ! For a virtual column (thus, a column that has no true elevation data), return the + ! "mean" elevation of the given elevation class. + ! + ! input/output variables + integer, intent(in) :: class ! elevation class + ! + ! local variables + character(len=*), parameter :: subname = 'mean_elevation_vc' + !----------------------------------------------------------------------- + + if (class < nglcec) then + mean_elevation_vc = 0.5_r8 * (elevclass(class) + elevclass(class+1)) + else if (class == nglcec) then + ! In the top elevation class; in this case, assignment of a "mean" elevation is + ! somewhat arbitrary + + if (nglcec > 1) then + mean_elevation_vc = 2.0_r8*elevclass(class) - elevclass(class-1) + else + ! entirely arbitrary + mean_elevation_vc = 1000._r8 + end if + else + write(6,*) 'ERROR in ', trim(subname), ': class out of bounds= ', class + call shr_sys_abort() + end if + + end function mean_elevation_vc + +end module mkglcmecMod diff --git a/tools/mksurfdata_esmf/src/mkharvestMod.F90 b/tools/mksurfdata_esmf/src/mkharvestMod.F90 new file mode 100644 index 0000000000..6e219a2164 --- /dev/null +++ b/tools/mksurfdata_esmf/src/mkharvestMod.F90 @@ -0,0 +1,322 @@ +module mkharvestMod + + !----------------------------------------------------------------------- + ! Make harvest and grazing data to add to the dynamic PFT file. + !----------------------------------------------------------------------- + + use ESMF + use pio + use shr_kind_mod , only : r8 => shr_kind_r8, r4=>shr_kind_r4, cs => shr_kind_cs, cl => shr_kind_cl + use shr_sys_mod , only : shr_sys_abort + use mkpioMod , only : pio_iotype, pio_ioformat, pio_iosystem + use mkpioMod , only : mkpio_get_rawdata, mkpio_get_rawdata_level, mkpio_get_dimlengths + use mkpioMod , only : mkpio_def_spatial_var, mkpio_iodesc_rawdata + use mkpioMod , only : mkpio_put_time_slice, mkpio_iodesc_output + use mkfileMod , only : mkfile_output + use mkesmfMod , only : regrid_rawdata, create_routehandle_r8, get_meshareas + use mkutilsMod , only : chkerr + use mkvarctl , only : root_task, ndiag, mpicom + use mkdiagnosticsMod , only : output_diagnostics_area + + implicit none + private + + ! public member functions + public :: mkharvest ! Calculate the harvest values on output grid + + ! private data members: + integer, parameter :: numharv = 9 ! number of harvest and grazing fields + integer, parameter :: harlen = 25 ! length of strings for harvest fieldnames + character(len=harlen), parameter :: harvest_fieldnames(numharv) = (/ & + 'HARVEST_VH1 ', & + 'HARVEST_VH2 ', & + 'HARVEST_SH1 ', & + 'HARVEST_SH2 ', & + 'HARVEST_SH3 ', & + 'GRAZING ', & + 'FERTNITRO_CFT ', & + 'UNREPRESENTED_PFT_LULCC', & + 'UNREPRESENTED_CFT_LULCC' & + /) + character(len=harlen), parameter :: harvest_const_fieldnames(numharv) = (/ & + 'CONST_HARVEST_VH1 ', & + 'CONST_HARVEST_VH2 ', & + 'CONST_HARVEST_SH1 ', & + 'CONST_HARVEST_SH2 ', & + 'CONST_HARVEST_SH3 ', & + 'CONST_GRAZING ', & + 'CONST_FERTNITRO_CFT ', & + 'UNREPRESENTED_PFT_LULCC', & + 'UNREPRESENTED_CFT_LULCC' & + /) + + type(ESMF_Mesh) :: mesh_i + type(ESMF_RouteHandle) :: routehandle_r8 + real(r8), allocatable :: frac_o(:) + + character(len=*) , parameter :: u_FILE_u = & + __FILE__ + +!================================================================================= +contains +!================================================================================= + + subroutine mkharvest(file_mesh_i, file_data_i, mesh_o, pioid_o, ntime, rc) + ! + ! Make harvest data for the dynamic PFT dataset. + ! This dataset consists of the normalized harvest or grazing fraction (0-1) of + ! the model. + ! + ! input/output variables: + character(len=*) , intent(in) :: file_mesh_i + character(len=*) , intent(in) :: file_data_i ! input data file name + type(ESMF_Mesh) , intent(in) :: mesh_o ! model mesh + type(file_desc_t) , intent(inout) :: pioid_o + integer, optional , intent(in) :: ntime + integer , intent(out) :: rc ! return code + + ! local variables: + type(file_desc_t) :: pioid_i + type(var_desc_t) :: pio_varid_i + type(var_desc_t) :: pio_varid_o + type(io_desc_t) :: pio_iodesc_i + type(io_desc_t) :: pio_iodesc_o + integer :: ns_i, ns_o ! input/output sizes + integer :: ni,no ! indices + integer :: k,l,m ! indices + integer :: ifld ! indices + integer :: dims2nd ! variable dimension lengths of 3rd dimension + character(len=cs) :: name2nd ! name of 2nd dimension + logical :: varexists ! true if variable exists on file + character(len=cs) :: varname_i ! input variable name + character(len=cs) :: varname_o ! output variable name + real(r8) , allocatable :: rmask_i(:) ! real value of input mask (read in) + integer , allocatable :: mask_i(:) ! integer value of rmask_i + real(r8) , allocatable :: data1d_i(:) ! input 1d data + real(r8) , allocatable :: data1d_o(:) ! otuput 1d data + real(r8) , allocatable :: data2d_o(:,:) ! output 2d data + real(r8) , allocatable :: read_data2d_i(:,:) + real(r8) , allocatable :: read_data2d_o(:,:) + real(r8) , allocatable :: area_i(:) ! areas on input mesh + real(r8) , allocatable :: area_o(:) ! areas on output mesh + integer :: rcode, ier ! error status + character(len=*), parameter :: subname = 'mkharvest' + !----------------------------------------------------------------------- + + rc = ESMF_SUCCESS + + if (root_task) then + write(ndiag,*) + write(ndiag,'(1x,80a1)') ('=',k=1,80) + write(ndiag,*) + write(ndiag,'(a)') 'Attempting to make harvest fields .....' + write(ndiag,'(a)') ' Input file is '//trim(file_data_i) + write(ndiag,'(a)') ' Input mesh file is '//trim(file_mesh_i) + end if + + ! Determine ns_o + call ESMF_MeshGet(mesh_o, numOwnedElements=ns_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Normally read in the harvesting file, and then regrid to output grid + rcode = pio_openfile(pio_iosystem, pioid_i, pio_iotype, trim(file_data_i), pio_nowrite) + + ! Read in input mesh + if (.not. ESMF_MeshIsCreated(mesh_i)) then + mesh_i = ESMF_MeshCreate(filename=trim(file_mesh_i), fileformat=ESMF_FILEFORMAT_ESMFMESH, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + end if + + ! Determine ns_i + call ESMF_MeshGet(mesh_i, numOwnedElements=ns_i, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Get the landmask from the file and reset the mesh mask based on that + allocate(rmask_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort() + allocate(mask_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort() + call mkpio_get_rawdata(pioid_i, 'LANDMASK', mesh_i, rmask_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + do ni = 1,ns_i + if (rmask_i(ni) > 0._r4) then + mask_i(ni) = 1 + else + mask_i(ni) = 0 + end if + end do + deallocate(rmask_i) + call ESMF_MeshSet(mesh_i, elementMask=mask_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! Create a route handle between the input and output mesh + ! NOTE: this must be done after mask_i is set in mesh_i + if (.not. ESMF_RouteHandleIsCreated(routehandle_r8)) then + allocate(frac_o(ns_o)) + call create_routehandle_r8(mesh_i=mesh_i, mesh_o=mesh_o, norm_by_fracs=.true., & + routehandle=routehandle_r8, frac_o=frac_o, rc=rc) + call ESMF_VMLogMemInfo("After create routehandle in "//trim(subname)) + end if + + ! Read in input 1d fields if they exists and map to output grid + do ifld = 1,numharv + varname_i = trim(harvest_fieldnames(ifld)) + if (.not. present(ntime)) then ! not transient, i.e. constant + varname_o = trim(harvest_const_fieldnames(ifld)) + else + varname_o = varname_i + end if + call mkharvest_check_input_var(pioid_i, trim(varname_i), varexists, dims2nd, name2nd) + if (varexists) then + if (dims2nd == 0) then + + ! 1d output + allocate(data1d_i(ns_i)) + allocate(data1d_o(ns_o)) + + ! read in input 1d variable + call mkpio_get_rawdata(pioid_i, varname_i, mesh_i, data1d_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! regrid input variable + call regrid_rawdata(mesh_i, mesh_o, routehandle_r8, data1d_i, data1d_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! write out mapped variable + if (present(ntime)) then + if (root_task) write(ndiag, '(a,i8)') subname//" writing out 1d "//trim(varname_o)//' at time ',ntime + rcode = pio_inq_varid(pioid_o, trim(varname_o), pio_varid_o) + call mkpio_iodesc_output(pioid_o, mesh_o, trim(varname_o), pio_iodesc_o, rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in making an iodesc for '//trim(varname_o)) + call pio_setframe(pioid_o, pio_varid_o, int(ntime, kind=Pio_Offset_Kind)) + call pio_write_darray(pioid_o, pio_varid_o, pio_iodesc_o, data1d_o, rcode) + call pio_freedecomp(pioid_o, pio_iodesc_o) + else + if (root_task) write(ndiag, '(a)') subname//" writing out 1d "//trim(varname_o) + call mkfile_output(pioid_o, mesh_o, trim(varname_o), data1d_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + end if + call pio_syncfile(pioid_o) + + ! Compare global areas on input and output grids for 1d variables + call output_diagnostics_area(mesh_i, mesh_o, mask_i, frac_o, & + data1d_i*0.01_r8, data1d_o*0.01_r8, trim(varname_o), percent=.false., ndiag=ndiag, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + deallocate(data1d_i) + deallocate(data1d_o) + + else ! 2d output + + ! Read in input data + allocate(read_data2d_i(dims2nd, ns_i)) + allocate(read_data2d_o(dims2nd, ns_o)) + call mkpio_get_rawdata(pioid_i, trim(varname_i), mesh_i, read_data2d_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! Regrid input input data + call regrid_rawdata(mesh_i, mesh_o, routehandle_r8, read_data2d_i, read_data2d_o, 1, dims2nd, rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + deallocate(read_data2d_i) + + ! Fill in output 2d array + allocate(data2d_o(ns_o,dims2nd)) + do l = 1,dims2nd + do no = 1,ns_o + data2d_o(no,l) = read_data2d_o(l,no) + end do + end do + deallocate(read_data2d_o) + + ! write out variable + if (present(ntime)) then + if (root_task) write(ndiag, '(a,i8)') subname//" writing out 2d "//trim(varname_o)//' at time ',ntime + rcode = pio_inq_varid(pioid_o, trim(varname_o), pio_varid_o) + call mkpio_iodesc_output(pioid_o, mesh_o, trim(varname_o), pio_iodesc_o, rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in making an iodesc for '//trim(varname_o)) + call pio_setframe(pioid_o, pio_varid_o, int(ntime, kind=Pio_Offset_Kind)) + call pio_write_darray(pioid_o, pio_varid_o, pio_iodesc_o, data2d_o, rcode) + call pio_freedecomp(pioid_o, pio_iodesc_o) + else + if (root_task) write(ndiag, '(a)') subname//" writing out 2d "//trim(varname_o) + call mkfile_output(pioid_o, mesh_o, trim(varname_o), data2d_o, lev1name=trim(name2nd), rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + end if + call pio_syncfile(pioid_o) + deallocate(data2d_o) + + end if + end if + end do + + if (.not. present(ntime)) then ! ...else we will reuse it + deallocate(frac_o) + call ESMF_RouteHandleDestroy(routehandle_r8, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + call ESMF_MeshDestroy(mesh_i, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + end if + + if (root_task) then + write (ndiag,'(a)') 'Successfully made harvest and grazing' + end if + + end subroutine mkharvest + + !================================================================================= + subroutine mkharvest_check_input_var(pioid, varname, varexists, dims2nd, name2nd) + + ! input/output variables + type(file_desc_t) , intent(inout) :: pioid + character(len=*) , intent(in) :: varname + logical , intent(out) :: varexists + integer , intent(out) :: dims2nd + character(len=*) , intent(out) :: name2nd + + ! local variable + type(var_desc_t) :: pio_varid + integer :: ndims ! number of variable dimension + integer :: dimids(3) ! variable dimension dim ids + integer :: dimlens(3) ! variable dimensions sizes + integer :: ifld ! index + integer :: rcode ! error status + character(len=*) , parameter :: subname = 'mkharvest_check_input_var' + !----------------------------------------------------------------------- + + dims2nd = -999 + name2nd = 'unset' + + call pio_seterrorhandling(pioid, PIO_BCAST_ERROR) + rcode = pio_inq_varid(pioid, varname, pio_varid) + call pio_seterrorhandling(pioid, PIO_INTERNAL_ERROR) + if (rcode == PIO_NOERR) then + varexists = .true. + else + varexists = .false. + end if + if (varexists) then + rcode = pio_inq_varndims(pioid, pio_varid, ndims) + if ( ndims == 2 )then + dims2nd = 0 + else if (ndims == 3 )then + rcode = pio_inq_vardimid(pioid, pio_varid, dimids) + rcode = pio_inq_dimlen(pioid, dimids(3), dimlens(3)) + dims2nd = dimlens(3) + rcode = pio_inq_vardimid(pioid, pio_varid, dimids) + rcode = pio_inq_dimname(pioid, dimids(3), name2nd) + else + write(*,*) 'ERROR:: bad dimensionality for variable = ',trim(varname) + call shr_sys_abort() + end if + if (root_task) then + write(ndiag,'(a)') " reading: "//trim(varname) + end if + else + if (root_task) then + write(ndiag,'(a)') " skipping: "//trim(varname) + end if + end if + + end subroutine mkharvest_check_input_var + +end module mkharvestMod diff --git a/tools/mksurfdata_esmf/src/mkindexmapMod.F90 b/tools/mksurfdata_esmf/src/mkindexmapMod.F90 new file mode 100644 index 0000000000..e653a752e0 --- /dev/null +++ b/tools/mksurfdata_esmf/src/mkindexmapMod.F90 @@ -0,0 +1,426 @@ +module mkindexmapMod + + !----------------------------------------------------------------------- + ! Module containing subroutines for making maps of index data. + ! + ! Includes routines for using an index map as indices into a lookup + ! table, to essentially paint-by-number some other field. + ! + ! WJS (2-1-12): There is a lookup_2d subroutine, but not a lookup_1d (or any other + ! dimensionality). That is simply because I needed lookup_2d, but have not yet needed a + ! routine of other dimensionalities. In the future, it would probably be helpful to at + ! least have lookup_1d and lookup_1d_netcdf. If this is done, see my notes under the + ! lookup_2d_netcdf routine for some thoughts on avoiding duplication. + !----------------------------------------------------------------------- + + use ESMF + use pio + use shr_kind_mod, only : r8 => shr_kind_r8, cs => shr_kind_cs + use shr_sys_mod , only : shr_sys_abort + + implicit none + private + + ! public types: + ! dim_slice_type: stores information about dimensions that we use for slicing a multi- + ! dimensional variable + type dim_slice_type + character(len=CS) :: name ! name of this dimension + integer :: val ! index to use for the slice + end type dim_slice_type + public :: dim_slice_type + + ! public member functions: + public :: lookup_2d ! create map based on a 2-d lookup table + public :: lookup_2d_netcdf ! wrapper to lookup_2d; first read table from netcdf file + public :: which_max ! get index of the maximum value in an array + +!------------------------------------------------------------------------------ +contains +!------------------------------------------------------------------------------ + + subroutine lookup_2d(index1, index2, lookup_table, fill_val, data, ierr, & + nodata, valid_entries, invalid_okay) + ! + ! Creates a data array using a paint-by-number approach according to a lookup table + ! + ! This routine operates on a 2-d lookup table. There are therefore two index arrays + ! (index1 and index2); these index arrays are on the same grid as the desired data array + ! (thus, index1, index2 and data must all have the same length). Each output point, n, is + ! then generally determined as: + ! + ! data(n) = lookup_table(index1(n), index2(n)) + ! + ! fill_val: value to put in data array where either: + ! (a) index1 or index2 are equal to nodata (if nodata is given) + ! Note that this condition does NOT result in ierr being set + ! (b) valid_entries(index1(n), index2(n)) is false (if valid_entries is given) + ! Note that this condition also results in ierr being set, unless invalid_okay is + ! present and .true. + ! (If valid_entries is not given, it is treated as being .true. everywhere) + ! (c) index1 or index2 out of range + ! Note that this condition also results in ierr being set + ! + ! ierr: error return code (if non-0, indicates first error encountered): + ! 0: no error + ! 1: attempt to assign values from the lookup table that are invalid according + ! to valid_entries (note: this is not considered an error if invalid_okay is + ! present and .true.) + ! 2: attempt to access an out-of-range index in lookup table + ! WJS (2-2-12): My main reason for using ierr rather than aborting in case of error + ! is to facilitate unit testing + ! + ! input/output variables + integer , intent(in) :: index1(:) ! index into dim 1 of lookup_table + integer , intent(in) :: index2(:) ! index into dim 2 of lookup_table + real(r8), intent(in) :: lookup_table(:,:) + real(r8), intent(in) :: fill_val ! value to put in data where we don't have a valid value (see above for details) + real(r8), intent(out):: data(:) ! output arary + integer , intent(out):: ierr ! error return code (0 = no error) + + ! nodata flag in index1 and index2 (see above for details): + integer, intent(in), optional :: nodata + + ! which entries are considered valid (see above for details): + logical, intent(in), optional :: valid_entries(:,:) + + ! invalid_okay: if true, then assigning fill_val because valid_entries is false does + ! NOT raise an error flag (invalid_okay defaults to false, meaning an error is + ! raised in this case): + logical, intent(in), optional :: invalid_okay + + ! local variables: + integer :: n + integer :: i1, i2 + integer :: data_size ! size of index1, index2 and data arrays + integer :: table_n1 ! size of dimension 1 of lookup table + integer :: table_n2 ! size of dimension 2 of lookup table + logical :: linvalid_okay ! local version of invalid_okay + logical, allocatable :: lvalid_entries(:,:) ! local version of valid_entries + character(len=*), parameter :: subname = 'lookup_2d' + !----------------------------------------------------------------------- + + ierr = 0 + + ! Error-check array sizes + + data_size = size(data) + if (size(index1) /= data_size .or. size(index2) /= data_size) then + write(6,*) subname//' ERROR: data array sizes do not match' + write(6,*) 'size(data) = ', data_size + write(6,*) 'size(index1) = ', size(index1) + write(6,*) 'size(index2) = ', size(index2) + call shr_sys_abort() + end if + + table_n1 = size(lookup_table,1) + table_n2 = size(lookup_table,2) + if (present(valid_entries)) then + if (size(valid_entries,1) /= table_n1 .or. size(valid_entries,2) /= table_n2) then + write(6,*) subname//' ERROR: size of valid_entries does not match lookup_table' + write(6,*) 'size(lookup_table) = ', table_n1, table_n2 + write(6,*) 'size(valid_entries) = ', size(valid_entries,1), & + size(valid_entries,2) + call shr_sys_abort() + end if + end if + + ! Set local version of invalid_okay & valid_entries + + if (present(invalid_okay)) then + linvalid_okay = invalid_okay + else + linvalid_okay = .false. + end if + + allocate(lvalid_entries(table_n1, table_n2)) + if (present(valid_entries)) then + lvalid_entries(:,:) = valid_entries(:,:) + else + lvalid_entries(:,:) = .true. + end if + + ! Do the lookups + + do n = 1, data_size + i1 = index1(n) + i2 = index2(n) + + ! First handle special cases: + + ! index is nodata flag (this is NOT an error) + if (present(nodata)) then + if (i1 == nodata .or. i2 == nodata) then + data(n) = fill_val + cycle + end if + end if + + ! index out of range + if (i1 <= 0 .or. i1 > table_n1 .or. & + i2 <= 0 .or. i2 > table_n2) then + data(n) = fill_val + if (ierr == 0) ierr = 2 + cycle + end if + + ! lookup table entry is invalid + if (.not. lvalid_entries(i1, i2)) then + data(n) = fill_val + if (.not. linvalid_okay) then + if (ierr == 0) ierr = 1 + end if + cycle + end if + + ! Finally, the "normal" case, if none of the special cases were triggered: + data(n) = lookup_table(i1, i2) + end do + + deallocate(lvalid_entries) + + end subroutine lookup_2d + + !------------------------------------------------------------------------------ + subroutine lookup_2d_netcdf(pioid, tablename, lookup_has_invalid, & + dimname1, dimname2, n_extra_dims, & + index1, index2, fill_val, data, ierr, & + extra_dims, nodata, invalid_okay) + ! + ! Wrapper to lookup_2d that first reads the lookup table from a netcdf file + ! + ! If lookup_has_invalid is false, then we treat all lookup table entries as valid data + ! (i.e., all valid_entries are true in the call to lookup_2d). If lookup_has_invalid is + ! true, then we read the _FillValue attribute for the lookup table variable, and consider + ! any table entry with value _FillValue to be an invalid entry, thus putting fill_val in + ! these data locations (and raising an error flag unless invalid_okay is present and + ! true). + ! + ! The dimension given by dimname1 -- with the associated indices given by index1 -- is the + ! fastest-varying dimension in the lookup table. Dimension dimname2 (associated with + ! index2) is the second-fastest-varying dimension. Similarly, extra_dims should be ordered + ! from faster-varying to slowest-varying dimension. (The first dimension in extra_dims is + ! the third-fastest-varying dimension in the lookup table.) + ! + ! n_extra_dims gives the number of extra dimensions (in addition to the first two) in the + ! lookup table. We take a single 2-d slice of the lookup table, by using a single value of + ! each of these other dimensions. If n_extra_dims > 0, then extra_dims must be present, + ! with at least n_extra_dims entries. Each entry in extra_dims gives the name of a + ! dimension and the dimension index to use for the slice. + ! + ! If size(extra_dims) > n_extra_dims, then we use the first n_extra_dims entries in + ! extra_dims. If n_extra_dims = 0, then extra_dims is ignored. + ! + ! Note that we ignore any coordinate variables associated with the dimensions of the + ! lookup table; we simply treat the lookup table indices as 1,2,3,... + ! + ! See the lookup_2d documentation for documentation of some other arguments + ! + ! WJS (2-1-12): Some thoughts on avoiding duplication if we eventually want similar + ! routines, lookup_1d_netcdf, lookup_3d_netcdf, etc.: + ! + ! Much of the code in lookup_2d_netcdf could then be pulled out to a shared subroutine + ! (e.g., much of the error-checking code). + ! + ! Or, maybe better: we could try to make a single lookup_netcdf subroutine that handles + ! 1-d, 2-d and any other dimensionality. To do that, we would (1) make a generic interface + ! (of which lookup_1d and lookup_2d would be implementations); (2) change the repeated + ! arguments in lookup_2d_netcdf (*1 and *2) to arrays -- maybe using an array of a derived + ! type containing these arguments; (3) if possible, initially read the lookup table into a + ! 1-d array (if the netcdf call allows reading a n-d array into a 1-d array) (if netcdf + ! doesn't allow this, then I think we could achieve the same thing by reading 1-d slices + ! of the lookup table in a loop, building the full lookup table as a long 1-d array); (4) + ! in the call to the generic 'lookup' function, reshape the 1-d lookup table + ! appropriately. (Note: I think it would be challenging to combine lookup_1d and lookup_2d + ! (etc.) into a single routine using a similar method.) + ! + ! input/output variables + type(file_desc_t) , intent(inout) :: pioid + character(len=*) , intent(in) :: tablename ! name of the lookup table variable + logical , intent(in) :: lookup_has_invalid ! should we use _FillValue? (see above) + character(len=*) , intent(in) :: dimname1 ! name of the first (fastest-varying) dimension of the lookup table + character(len=*) , intent(in) :: dimname2 ! name of the second dimension of the lookup table + integer , intent(in) :: n_extra_dims ! number of extra dimensions in the lookup table + + ! The following arguments are passed directly to lookup_2d: + integer , intent(in) :: index1(:) ! index into dim 1 of lookup table + integer , intent(in) :: index2(:) ! index into dim 2 of lookup table + real(r8) , intent(in) :: fill_val ! value to put in data where we don't have a valid value + real(r8) , intent(out) :: data(:) ! output array + integer , intent(out) :: ierr ! error return code from the call to lookup_2d + + ! slice to use if lookup table variable has more than 2 dimensions: + type(dim_slice_type), intent(in), optional :: extra_dims(:) + + ! nodata flag in index1 and index2, passed directly to lookup_2d: + integer , intent(in), optional :: nodata + + ! flag for whether trying to use a lookup table value that is equal to the _FillValue + ! should raise an error flag + ! (irrelevant if lookup_has_invalid is .false.) + ! (passed directly to lookup_2d - see the documentation there for more details) + logical , intent(in), optional :: invalid_okay + + ! !LOCAL VARIABLES: + type(var_desc_t) :: pio_varid + integer :: ndims ! total number of dimensions of lookup table + integer :: ndims_expected ! value we expect for ndims, for error checking + integer :: i ! index + integer :: rcode ! error status + real(r8) :: table_fillval ! value of the _FillValue attribute for the lookup table + character(len=CS), allocatable :: dimnames(:) ! dimension names + integer , allocatable :: dimids(:) ! dimension ids + integer , allocatable :: dimlens(:) ! dimension lengths + integer , allocatable :: starts(:) ! starting indices for reading lookup table + integer , allocatable :: counts(:) ! dimension counts for reading lookup table + real(r8), allocatable :: lookup_table(:,:) + logical , allocatable :: valid_entries(:,:) ! which entries of the lookup table are considered valid + character(len=*), parameter :: subname = 'lookup_2d_netcdf' + !----------------------------------------------------------------------- + + ! Error-check extra_dims + if (n_extra_dims > 0) then + if (.not. present(extra_dims)) then + write(6,*) subname//' ERROR: extra_dims must be present for n_extra_dims > 0' + call shr_sys_abort() + end if + + if (size(extra_dims) < n_extra_dims) then + write(6,*) subname//' ERROR: not enough extra dimensions given' + write(6,*) 'n_extra_dims = ', n_extra_dims + write(6,*) 'size(extra_dims) = ', size(extra_dims) + call shr_sys_abort() + end if + end if + + ! Determine number of expected dimensions in the table, and actual number of + ! dimensions in the netcdf file + + ndims_expected = 2 + n_extra_dims + + rcode = pio_inq_varid(pioid, trim(tablename), pio_varid) + rcode = pio_inq_varndims(pioid, pio_varid, ndims) + if (ndims /= ndims_expected) then + write(6,*) subname//' ERROR: unexpected number of dimensions in ', & + trim(tablename) + write(6,*) 'ndims = ', ndims + write(6,*) 'expected (based on n_extra_dims): ', ndims_expected + call shr_sys_abort() + end if + + ! Get dimension names & sizes, and error-check them + allocate(dimids(ndims), dimlens(ndims), dimnames(ndims)) + rcode = pio_inq_vardimid (pioid, pio_varid, dimids) + do i = 1, ndims + rcode = pio_inq_dimname (pioid, dimids(i), dimnames(i)) + rcode = pio_inq_dimlen (pioid, dimids(i), dimlens(i)) + end do + call check_dimname(dimnames(1), dimname1, 1) + call check_dimname(dimnames(2), dimname2, 2) + do i = 1, n_extra_dims + call check_dimname(dimnames(2+i), extra_dims(i)%name, 2+i) + call check_dimsize(dimlens(2+i), extra_dims(i)%val, 2+i) + end do + + ! Read the lookup table; if the given variable has more than 2 dimensions, we read + ! a single 2-d slice + + allocate(starts(ndims), counts(ndims)) + allocate(lookup_table(dimlens(1), dimlens(2))) + starts(1:2) = 1 + counts(1:2) = dimlens(1:2) + do i = 1, n_extra_dims + starts(2+i) = extra_dims(i)%val + counts(2+i) = 1 + end do + rcode = pio_get_var(pioid, pio_varid, starts, counts, lookup_table) + + !allocate(lookup_table(dimlens(1), dimlens(2))) + !rcode = pio_get_var(pioid, pio_varid, lookup_table) + + ! Determine which entries are valid + allocate(valid_entries(size(lookup_table, 1), size(lookup_table, 2))) + valid_entries(:,:) = .true. + if (lookup_has_invalid) then + rcode = pio_get_att(pioid, pio_varid, '_FillValue', table_fillval) + where (lookup_table == table_fillval) + valid_entries = .false. + end where + end if + + ! Do the lookups + call lookup_2d(index1, index2, lookup_table, fill_val, data, ierr, nodata=nodata, & + valid_entries=valid_entries, invalid_okay=invalid_okay) + + deallocate(valid_entries) + deallocate(lookup_table) + deallocate(starts, counts) + deallocate(dimids, dimlens, dimnames) + + contains + + !------------------------------------------------------------------------------ + subroutine check_dimname(actual, expected, i) + ! Make sure names are equal; if not, stop with an error message + + character(len=*), intent(in) :: actual, expected + integer , intent(in) :: i ! dimension number, for output purposes + + if (actual /= expected) then + write(6,*) subname//' ERROR: unexpected dimension name in ', trim(tablename) + write(6,*) 'dimension #', i + write(6,*) 'actual: ', trim(actual) + write(6,*) 'expected: ', trim(expected) + call shr_sys_abort() + end if + end subroutine check_dimname + + !------------------------------------------------------------------------------ + subroutine check_dimsize(length, index, i) + ! Make sure dimension length is long enough; if not, stop with an error message + + integer, intent(in) :: length, index + integer, intent(in) :: i ! dimension number, for output purposes + + if (index > length) then + write(6,*) subname//' ERROR: desired index exceeds dimension length in ', & + trim(tablename) + write(6,*) 'dimension #', i + write(6,*) 'index: ', index + write(6,*) 'length: ', length + call shr_sys_abort() + end if + end subroutine check_dimsize + + end subroutine lookup_2d_netcdf + + !------------------------------------------------------------------------------ + subroutine which_max(arr, maxval, maxindex, lbound) + ! + ! Returns maximum value in arr along with the index of the maximum value + ! If multiple values are tied, returns index of the first maximum + ! + ! input/output variables + real(r8), intent(in) :: arr(:) + real(r8), intent(out):: maxval ! maximum value in arr(:) + integer , intent(out):: maxindex ! first index of maxval + integer , intent(in), optional :: lbound ! lower bound of indices of arr; + ! if not supplied, assumed to be 1: + ! local variables + integer :: i + !----------------------------------------------------------------------- + + maxindex = 1 + maxval = arr(1) + do i = 2, size(arr) + if (arr(i) > maxval) then + maxindex = i + maxval = arr(i) + end if + end do + if (present(lbound)) then + maxindex = maxindex + (lbound - 1) + end if + end subroutine which_max + +end module mkindexmapMod diff --git a/tools/mksurfdata_esmf/src/mkinputMod.F90 b/tools/mksurfdata_esmf/src/mkinputMod.F90 new file mode 100644 index 0000000000..9c8564df03 --- /dev/null +++ b/tools/mksurfdata_esmf/src/mkinputMod.F90 @@ -0,0 +1,474 @@ +module mkinputMod + + !----------------------------------------------------------------------- + ! Module containing input namelist settings + !----------------------------------------------------------------------- + + use shr_kind_mod , only : r8 => shr_kind_r8 + use shr_kind_mod , only : CS => shr_kind_CS, CL => shr_kind_CL, CX => shr_kind_CX + use shr_sys_mod , only : shr_sys_abort + use mkvarctl + + implicit none + private + +#include + + ! --------------------- + ! routines + ! --------------------- + + public :: read_namelist_input ! Read the input control namelist + public :: bcast_namelist_input ! Broadcast the namelist to all processors + public :: check_namelist_input ! Check the input control namelist for errors + public :: write_namelist_input ! Write information on the control namelist + + ! --------------------- + ! variables + ! --------------------- + + character(CL) , public :: fgrddat ! grid data file + character(CL) , public :: fsurdat ! output surface data file name (if blank, do not output a surface dataset) + character(CL) , public :: fsurlog ! output surface log file name + character(CL) , public :: fdyndat ! dynamic landuse data file name + character(CL) , public :: fhrvname ! generic harvest filename + character(CL) , public :: furbname ! generic transient urban land cover filename + character(CL) , public :: flakname ! generic lake filename + + character(CS) , public :: mksrf_grid_name = ' ' ! Name of this grid + integer , public :: grid_size ! Number of columne in the grid + + character(CX) , public :: mksrf_fgrid_mesh = ' ' ! land grid file name to use + integer , public :: mksrf_fgrid_mesh_nx = -999 + integer , public :: mksrf_fgrid_mesh_ny = -999 + + character(CX) , public :: mksrf_fvegtyp = ' ' ! vegetation data file name + character(CX) , public :: mksrf_fvegtyp_mesh = ' ' ! vegetation mesh file name + + character(CX) , public :: mksrf_fhrvtyp = ' ' ! harvest data file name + character(CX) , public :: mksrf_fhrvtyp_mesh = ' ' ! harvest mesh file name + + character(CX) , public :: mksrf_fsoicol = ' ' ! soil color data file name + character(CX) , public :: mksrf_fsoicol_mesh = ' ' ! soil color mesh file name + + character(CX) , public :: mksrf_fsoitex = ' ' ! soil texture mapunit data file name + character(CX) , public :: mksrf_fsoitex_lookup = ' ' ! soil texture lookup data file name + character(CX) , public :: mksrf_fsoitex_mesh = ' ' ! soil texture mesh file name + + character(CX) , public :: mksrf_fmax = ' ' ! fmax data file name + character(CX) , public :: mksrf_fmax_mesh = ' ' ! fmax mesh file name + + character(CX) , public :: mksrf_fsoildepth = ' ' ! soil depth file name + character(CX) , public :: mksrf_fsoildepth_mesh = ' ' ! soil depth file name + + character(CX) , public :: mksrf_fabm = ' ' ! ag fire peak month and + character(CX) , public :: mksrf_fabm_mesh = ' ' ! ag fire peak month and + + character(CX) , public :: mksrf_fpeat = ' ' ! peatlands and + character(CX) , public :: mksrf_fpeat_mesh = ' ' ! peatlands and + + character(CX) , public :: mksrf_fgdp = ' ' ! gdp data file names + character(CX) , public :: mksrf_fgdp_mesh = ' ' ! gdp mesh file names + + character(CX) , public :: mksrf_fpctlak = ' ' ! percent lake data file name + character(CX) , public :: mksrf_fpctlak_mesh = ' ' ! percent lake file name + character(CX) , public :: mksrf_flakdep = ' ' ! lake depth data file name + character(CX) , public :: mksrf_flakdep_mesh = ' ' ! lake depth file name + + character(CX) , public :: mksrf_fwetlnd = ' ' ! inland wetlands data file name + character(CX) , public :: mksrf_fwetlnd_mesh = ' ' ! inland wetlands mesh file name + + character(CX) , public :: mksrf_furban = ' ' ! urban data file name + character(CX) , public :: mksrf_furban_mesh = ' ' ! urban mesh file name + + character(CX) , public :: mksrf_fglacier = ' ' ! glacier data file name + character(CX) , public :: mksrf_fglacier_mesh = ' ' ! glacier mesh file name + + character(CX) , public :: mksrf_fglacierregion = ' ' ! glacier region data file name + character(CX) , public :: mksrf_fglacierregion_mesh = ' ' ! glacier region mesh file name + + character(CX) , public :: mksrf_furbtopo = ' ' ! urban topography data file name + character(CX) , public :: mksrf_furbtopo_mesh = ' ' ! urban topography mesh file name + + character(CX) , public :: mksrf_flai = ' ' ! lai data filename + character(CX) , public :: mksrf_flai_mesh = ' ' ! lai mesh filename + + character(CX) , public :: mksrf_fdynuse = ' ' ! ascii file containing names of dynamic land use files + character(CX) , public :: mksrf_fdynuse_mesh = ' ' ! ascii file containing names of dynamic land use files + + character(CX) , public :: mksrf_fvocef = ' ' ! VOC Emission Factor data file name + character(CX) , public :: mksrf_fvocef_mesh = ' ' ! VOC Emission Factor mesh file name + + character(CX) , public :: mksrf_ftopostats = ' ' ! topography statistics data file name + character(CX) , public :: mksrf_ftopostats_mesh = ' ' ! topography statistics mesh file name + character(CX) , public :: mksrf_ftopostats_override = ' ' ! read STD_ELEV and SLOPE from this file + + character(CX) , public :: mksrf_fvic = ' ' ! VIC parameters data file name + character(CX) , public :: mksrf_fvic_mesh = ' ' ! VIC parameters mesh file name + + character(CX) , public :: mksrf_irrig = ' ' ! TODO: should this namelist be here? + character(CX) , public :: mksrf_irrig_mesh = ' ' ! TODO: should this namelist be here? + + character(CS) , public :: gitdescribe = ' ' ! Description of model version from git + character(CS) , public :: logname = ' ' ! user name + character(CS) , public :: hostname = ' ' ! machine name + + logical , public :: create_esmf_pet_files = .false. ! Always create ESMF PET files (.false. if only on error) + logical , public :: urban_skip_abort_on_invalid_data_check + + character(len=*), parameter :: u_FILE_u = & + __FILE__ + +!=============================================================== +contains +!=============================================================== + + subroutine read_namelist_input() + + ! Read in input namelist + + ! local variables + integer :: ier + integer :: k + integer :: fileunit + logical :: lexist + character(len=*), parameter :: subname = 'read_namelist_input' + ! ------------------------------------------------------------ + + namelist /mksurfdata_input/ & + mksrf_grid_name, & + mksrf_fvegtyp, & + mksrf_fvegtyp_mesh, & + mksrf_fhrvtyp, & + mksrf_fhrvtyp_mesh, & + mksrf_fsoitex, & + mksrf_fsoitex_lookup, & + mksrf_fsoitex_mesh, & + mksrf_fsoicol, & + mksrf_fsoicol_mesh, & + mksrf_fvocef, & + mksrf_fvocef_mesh, & + mksrf_fpctlak, & + mksrf_fpctlak_mesh, & + mksrf_flakdep, & + mksrf_flakdep_mesh, & + mksrf_fwetlnd, & + mksrf_fwetlnd_mesh, & + mksrf_fglacier, & + mksrf_fglacier_mesh, & + mksrf_fglacierregion, & + mksrf_fglacierregion_mesh, & + mksrf_furbtopo, & + mksrf_furbtopo_mesh, & + mksrf_fmax, & + mksrf_fmax_mesh, & + mksrf_furban, & + mksrf_furban_mesh, & + mksrf_flai, & + mksrf_flai_mesh, & + mksrf_fdynuse, & + mksrf_fdynuse_mesh, & + mksrf_fgdp, & + mksrf_fgdp_mesh, & + mksrf_fpeat, & + mksrf_fpeat_mesh, & + mksrf_fsoildepth, & + mksrf_fsoildepth_mesh, & + mksrf_fabm, & + mksrf_fabm_mesh, & + mksrf_ftopostats, & + mksrf_ftopostats_mesh, & + mksrf_ftopostats_override, & + mksrf_fvic, & + mksrf_fvic_mesh, & + mksrf_fgrid_mesh, & + mksrf_fgrid_mesh_nx, & + mksrf_fgrid_mesh_ny, & + numpft, & + no_inlandwet, & + nglcec, & + gitdescribe, & + logname, & + hostname, & + outnc_large_files, & + outnc_double, & + outnc_dims, & + outnc_vic, & + outnc_3dglc, & + fsurdat, & + fdyndat, & + fsurlog, & + std_elev, & + create_esmf_pet_files, & + urban_skip_abort_on_invalid_data_check + + ! Set default namelist values - make these the defaults in gen_mksurfdata_namelist.py + outnc_large_files = .false. + outnc_double = .true. + outnc_vic = .false. + outnc_3dglc = .false. + no_inlandwet = .true. + urban_skip_abort_on_invalid_data_check = .false. ! default value for bug work around + + if (root_task) then + write(ndiag,*) 'Attempting to initialize control settings .....' + end if + + if (root_task) then + read(5, nml=mksurfdata_input, iostat=ier) + if (ier > 0) then + call shr_sys_abort(subname//' error reading in mksurfdata_input namelist from standard input') + end if + grid_size = mksrf_fgrid_mesh_nx * mksrf_fgrid_mesh_ny + if ( mksrf_grid_name == ' ' )then + write(mksrf_grid_name,'("Cols",I7.7)') grid_size + end if + end if + + end subroutine read_namelist_input + + !=============================================================== + + subroutine bcast_namelist_input() + + ! Braodcast the namelist to all processors + + ! local variables + integer :: ier + + call mpi_bcast (mksrf_fgrid_mesh, len(mksrf_fgrid_mesh), MPI_CHARACTER, 0, mpicom, ier) + call mpi_bcast (mksrf_fgrid_mesh_nx, 1, MPI_INTEGER, 0, mpicom, ier) + call mpi_bcast (mksrf_fgrid_mesh_ny, 1, MPI_INTEGER, 0, mpicom, ier) + call mpi_bcast (grid_size, 1, MPI_INTEGER, 0, mpicom, ier) + call mpi_bcast (mksrf_grid_name, len(mksrf_grid_name), MPI_CHARACTER, 0, mpicom, ier) + + call mpi_bcast (mksrf_fvegtyp, len(mksrf_fvegtyp), MPI_CHARACTER, 0, mpicom, ier) + call mpi_bcast (mksrf_fvegtyp_mesh, len(mksrf_fvegtyp_mesh), MPI_CHARACTER, 0, mpicom, ier) + + call mpi_bcast (mksrf_fhrvtyp, len(mksrf_fhrvtyp), MPI_CHARACTER, 0, mpicom, ier) + call mpi_bcast (mksrf_fhrvtyp_mesh, len(mksrf_fhrvtyp_mesh), MPI_CHARACTER, 0, mpicom, ier) + + call mpi_bcast (mksrf_fsoitex, len(mksrf_fsoitex), MPI_CHARACTER, 0, mpicom, ier) + call mpi_bcast (mksrf_fsoitex_lookup, len(mksrf_fsoitex_lookup), MPI_CHARACTER, 0, mpicom, ier) + call mpi_bcast (mksrf_fsoitex_mesh, len(mksrf_fsoitex_mesh), MPI_CHARACTER, 0, mpicom, ier) + + call mpi_bcast (mksrf_fmax, len(mksrf_fmax), MPI_CHARACTER, 0, mpicom, ier) + call mpi_bcast (mksrf_fmax_mesh, len(mksrf_fmax_mesh), MPI_CHARACTER, 0, mpicom, ier) + + call mpi_bcast (mksrf_fsoicol, len(mksrf_fsoicol), MPI_CHARACTER, 0, mpicom, ier) + call mpi_bcast (mksrf_fsoicol_mesh, len(mksrf_fsoicol_mesh), MPI_CHARACTER, 0, mpicom, ier) + + call mpi_bcast (mksrf_fsoildepth, len(mksrf_fsoildepth), MPI_CHARACTER, 0, mpicom, ier) + call mpi_bcast (mksrf_fsoildepth_mesh, len(mksrf_fsoildepth_mesh), MPI_CHARACTER, 0, mpicom, ier) + + call mpi_bcast (mksrf_fabm, len(mksrf_fabm), MPI_CHARACTER, 0, mpicom, ier) + call mpi_bcast (mksrf_fabm_mesh, len(mksrf_fabm_mesh), MPI_CHARACTER, 0, mpicom, ier) + + call mpi_bcast (mksrf_fpeat, len(mksrf_fpeat), MPI_CHARACTER, 0, mpicom, ier) + call mpi_bcast (mksrf_fpeat_mesh, len(mksrf_fpeat_mesh), MPI_CHARACTER, 0, mpicom, ier) + + call mpi_bcast (mksrf_fgdp, len(mksrf_fgdp), MPI_CHARACTER, 0, mpicom, ier) + call mpi_bcast (mksrf_fgdp_mesh, len(mksrf_fgdp_mesh), MPI_CHARACTER, 0, mpicom, ier) + + call mpi_bcast (mksrf_fpctlak, len(mksrf_fpctlak), MPI_CHARACTER, 0, mpicom, ier) + call mpi_bcast (mksrf_fpctlak_mesh, len(mksrf_fpctlak_mesh), MPI_CHARACTER, 0, mpicom, ier) + call mpi_bcast (mksrf_flakdep, len(mksrf_flakdep), MPI_CHARACTER, 0, mpicom, ier) + call mpi_bcast (mksrf_flakdep_mesh, len(mksrf_flakdep_mesh), MPI_CHARACTER, 0, mpicom, ier) + + call mpi_bcast (mksrf_fwetlnd, len(mksrf_fwetlnd), MPI_CHARACTER, 0, mpicom, ier) + call mpi_bcast (mksrf_fwetlnd_mesh, len(mksrf_fwetlnd_mesh), MPI_CHARACTER, 0, mpicom, ier) + + call mpi_bcast (mksrf_furban, len(mksrf_furban), MPI_CHARACTER, 0, mpicom, ier) + call mpi_bcast (mksrf_furban_mesh, len(mksrf_furban_mesh), MPI_CHARACTER, 0, mpicom, ier) + + call mpi_bcast (mksrf_furbtopo, len(mksrf_furbtopo), MPI_CHARACTER, 0, mpicom, ier) + call mpi_bcast (mksrf_furbtopo_mesh, len(mksrf_furbtopo_mesh), MPI_CHARACTER, 0, mpicom, ier) + + call mpi_bcast (mksrf_fglacier, len(mksrf_fglacier), MPI_CHARACTER, 0, mpicom, ier) + call mpi_bcast (mksrf_fglacier_mesh, len(mksrf_fglacier_mesh), MPI_CHARACTER, 0, mpicom, ier) + + call mpi_bcast (mksrf_fglacierregion, len(mksrf_fglacierregion), MPI_CHARACTER, 0, mpicom, ier) + call mpi_bcast (mksrf_fglacierregion_mesh, len(mksrf_fglacierregion_mesh), MPI_CHARACTER, 0, mpicom, ier) + + call mpi_bcast (mksrf_flai, len(mksrf_flai), MPI_CHARACTER, 0, mpicom, ier) + call mpi_bcast (mksrf_flai_mesh, len(mksrf_flai_mesh), MPI_CHARACTER, 0, mpicom, ier) + + call mpi_bcast (mksrf_fvocef, len(mksrf_fvocef), MPI_CHARACTER, 0, mpicom, ier) + call mpi_bcast (mksrf_fvocef_mesh, len(mksrf_fvocef_mesh), MPI_CHARACTER, 0, mpicom, ier) + + call mpi_bcast (mksrf_ftopostats, len(mksrf_ftopostats), MPI_CHARACTER, 0, mpicom, ier) + call mpi_bcast (mksrf_ftopostats_mesh, len(mksrf_ftopostats_mesh), MPI_CHARACTER, 0, mpicom, ier) + call mpi_bcast (mksrf_ftopostats_override, len(mksrf_ftopostats_override), MPI_CHARACTER, 0, mpicom, ier) + + call mpi_bcast (mksrf_fvic, len(mksrf_fvic), MPI_CHARACTER, 0, mpicom, ier) + call mpi_bcast (mksrf_fvic_mesh, len(mksrf_fvic_mesh), MPI_CHARACTER, 0, mpicom, ier) + + call mpi_bcast (mksrf_fdynuse, len(mksrf_fdynuse), MPI_CHARACTER, 0, mpicom, ier) + call mpi_bcast (mksrf_fdynuse_mesh, len(mksrf_fdynuse_mesh), MPI_CHARACTER, 0, mpicom, ier) + + call mpi_bcast (fsurdat, len(fsurdat), MPI_CHARACTER, 0, mpicom, ier) + call mpi_bcast (fdyndat, len(fdyndat), MPI_CHARACTER, 0, mpicom, ier) + + call mpi_bcast (outnc_dims, 1, MPI_INTEGER, 0, mpicom, ier) + call mpi_bcast (outnc_large_files, 1, MPI_LOGICAL, 0, mpicom, ier) + call mpi_bcast (outnc_double, 1, MPI_LOGICAL, 0, mpicom, ier) + call mpi_bcast (outnc_1d, 1, MPI_LOGICAL, 0, mpicom, ier) + call mpi_bcast (outnc_vic, 1, MPI_LOGICAL, 0, mpicom, ier) + call mpi_bcast (outnc_3dglc, 1, MPI_LOGICAL, 0, mpicom, ier) + + call mpi_bcast (urban_skip_abort_on_invalid_data_check, 1, MPI_LOGICAL, 0, mpicom, ier) + call mpi_bcast (create_esmf_pet_files, 1, MPI_LOGICAL, 0, mpicom, ier) + call mpi_bcast (numpft, 1, MPI_INTEGER, 0, mpicom, ier) + call mpi_bcast (no_inlandwet, 1, MPI_LOGICAL, 0, mpicom, ier) + call mpi_bcast (std_elev, 1, MPI_REAL, 0, mpicom, ier) + + call mpi_bcast (gitdescribe, len(gitdescribe), MPI_CHARACTER, 0, mpicom, ier) + call mpi_bcast (logname, len(logname), MPI_CHARACTER, 0, mpicom, ier) + call mpi_bcast (hostname, len(hostname), MPI_CHARACTER, 0, mpicom, ier) + + end subroutine bcast_namelist_input + + !=============================================================== + subroutine check_namelist_input() + + ! error check on namelist input + if (mksrf_fgrid_mesh /= ' ')then + fgrddat = mksrf_fgrid_mesh + else + call shr_sys_abort(" must specify mksrf_fgrid_mesh") + endif + + if (nglcec <= 0) then + call shr_sys_abort('nglcec must be at least 1') + end if + + if (mksrf_fgrid_mesh_ny == 1) then + outnc_1d = .true. + outnc_dims = 1 + else + outnc_1d = .false. + outnc_dims = 2 + end if + + end subroutine check_namelist_input + + !=============================================================== + subroutine write_namelist_input() + + ! Write out namelist input to log file + ! Note - need to call this after ndiag has been set + + ! local variables + integer :: k + ! ------------------------------------------------------------ + + if (root_task) then + write(ndiag,'(a)')'Grid_name: '//trim(mksrf_grid_name) + write(ndiag,'(a)')'Input rawdata files and corresponding meshes' + write(ndiag,'(a)')' PFTs from: '//trim(mksrf_fvegtyp) + write(ndiag,'(a)')' mesh for pft '//trim(mksrf_fvegtyp_mesh) + write(ndiag,*) + write(ndiag,'(a)')' percent lake from: '//trim(mksrf_fpctlak) + write(ndiag,'(a)')' mesh for percent lake '//trim(mksrf_fpctlak_mesh) + write(ndiag,'(a)')' lake depth from: '//trim(mksrf_flakdep) + write(ndiag,'(a)')' mesh for lake depth '//trim(mksrf_flakdep_mesh) + write(ndiag,*) + write(ndiag,'(a)')' inland wetland from: '//trim(mksrf_fwetlnd) + write(ndiag,'(a)')' mesh for wetland '//trim(mksrf_fwetlnd_mesh) + write(ndiag,*) + write(ndiag,'(a)')' soil texture mapunits from: '//trim(mksrf_fsoitex) + write(ndiag,'(a)')' soil texture (sand/clay, orgc) lookup: '//trim(mksrf_fsoitex_lookup) + write(ndiag,'(a)')' mesh for soil texture '//trim(mksrf_fsoitex_mesh) + write(ndiag,*) + write(ndiag,'(a)')' soil color from: '//trim(mksrf_fsoicol) + write(ndiag,'(a)')' mesh for soil color '//trim(mksrf_fsoicol_mesh) + write(ndiag,*) + write(ndiag,'(a)')' fmax from: '//trim(mksrf_fmax) + write(ndiag,'(a)')' mesh for fmax '//trim(mksrf_fmax_mesh) + write(ndiag,*) + write(ndiag,'(a)')' soil depth from: '//trim(mksrf_fsoildepth) + write(ndiag,'(a)')' mesh for soil depth '//trim(mksrf_fsoildepth_mesh) + write(ndiag,*) + write(ndiag,'(a)')' VOC emission factors from: '//trim(mksrf_fvocef) + write(ndiag,'(a)')' mesh for VOC pct emis '//trim(mksrf_fvocef_mesh) + write(ndiag,*) + write(ndiag,'(a)')' gdp from: '//trim(mksrf_fgdp) + write(ndiag,'(a)')' mesh for gdp '//trim(mksrf_fgdp_mesh) + write(ndiag,*) + write(ndiag,'(a)')' peat from: '//trim(mksrf_fpeat) + write(ndiag,'(a)')' mesh for peatlands '//trim(mksrf_fpeat_mesh) + write(ndiag,*) + write(ndiag,'(a)')' harvest from: '//trim(mksrf_fhrvtyp) + write(ndiag,'(a)')' mesh for harvest '//trim(mksrf_fhrvtyp_mesh) + write(ndiag,*) + write(ndiag,'(a)')' topography statistics from: '//trim(mksrf_ftopostats) + write(ndiag,'(a)')' mesh for topography stats '//trim(mksrf_ftopostats_mesh) + write(ndiag,*) + write(ndiag,'(a)')' glaciers from: '//trim(mksrf_fglacier) + write(ndiag,'(a,i4,a)')' with: ',nglcec,' glacier elevation classes' + write(ndiag,'(a)')' mesh for glacier '//trim(mksrf_fglacier_mesh) + write(ndiag,'(a)')' glacier region ID from: '//trim(mksrf_fglacierregion) + write(ndiag,'(a)')' mesh for glacier region '//trim(mksrf_fglacierregion_mesh) + write(ndiag,*) + write(ndiag,'(a)')' urban from: '//trim(mksrf_furban) + write(ndiag,'(a)')' mesh for urban '//trim(mksrf_furban_mesh) + write(ndiag,*) + write(ndiag,'(a)')' urban topography from: '//trim(mksrf_furbtopo) + write(ndiag,'(a)')' mesh for urban topography '//trim(mksrf_furbtopo_mesh) + write(ndiag,*) + write(ndiag,'(a)')' mesh for lai/sai '//trim(mksrf_flai_mesh) + write(ndiag,'(a)')' mesh for ag fire pk month '//trim(mksrf_fabm_mesh) + write(ndiag,*) + write(ndiag,'(a)')' abm from: '//trim(mksrf_fabm) + write(ndiag,*) + write(ndiag,'(a)')' VIC parameters from: '//trim(mksrf_fvic) + write(ndiag,'(a)')' mesh for VIC parameters '//trim(mksrf_fvic_mesh) + write(ndiag,*) + if (mksrf_fdynuse /= ' ') then + write(ndiag,'(a)')' mksrf_fdynuse = '//trim(mksrf_fdynuse) + end if + write(ndiag,*) + write(ndiag,'(1x,80a1)') ('=',k=1,80) + write(ndiag,'(a)')'Model grid configuration variables' + write(ndiag,'(a)')' mksrf_fgrid_mesh = '//trim(mksrf_fgrid_mesh) + write(ndiag,'(a,i8)')' nlon= ',mksrf_fgrid_mesh_nx + write(ndiag,'(a,i8)')' nlat= ',mksrf_fgrid_mesh_ny + write(ndiag,'(a,i8)')'Grid_size: ', grid_size + write(ndiag,*) + write(ndiag,'(1x,80a1)') ('=',k=1,80) + write(ndiag,*) + write(ndiag,'(a)')'Output configuration variables' + if (outnc_1d) then + write(ndiag,'(a)')' output file is 1d format' + else + write(ndiag,'(a)')' output file is 2d lat/lon format' + end if + if ( outnc_large_files ) then + write(ndiag,'(a)')' Output file in NetCDF 64-bit large_files format' + end if + if ( outnc_double )then + write(ndiag,'(a)')' Output ALL data in file as 64-bit' + else + write(ndiag,'(a)')' Output ALL data in file as 32-bit' + end if + if ( outnc_vic )then + write(ndiag,'(a)')' Output VIC fields' + end if + if ( outnc_3dglc )then + write(ndiag,'(a)')' Output optional 3D glacier fields (mostly used for verification of the glacier model)' + end if + if (create_esmf_pet_files) then + write(ndiag,'(a)')' Always output ESMF PET files' + else + write(ndiag,'(a)')' Only output ESMF PET files if fatal errors happen in ESMF' + end if + if (urban_skip_abort_on_invalid_data_check) then + write(ndiag, '(a)') " WARNING: aborting on invalid data check in urban has been disabled!" + write(ndiag, '(a)') " WARNING: urban data may be invalid!" + end if + flush(ndiag) + end if + + end subroutine write_namelist_input + +end module mkinputMod diff --git a/tools/mksurfdata_esmf/src/mklaiMod.F90 b/tools/mksurfdata_esmf/src/mklaiMod.F90 new file mode 100644 index 0000000000..ba1014c2b9 --- /dev/null +++ b/tools/mksurfdata_esmf/src/mklaiMod.F90 @@ -0,0 +1,358 @@ +module mklaiMod + + !----------------------------------------------------------------------- + ! Make LAI/SAI/height data + !----------------------------------------------------------------------- + + use ESMF + use pio + use shr_kind_mod , only : r8 => shr_kind_r8, r4=>shr_kind_r4 + use shr_sys_mod , only : shr_sys_abort + use mkpioMod , only : pio_iotype, pio_ioformat, pio_iosystem + use mkpioMod , only : mkpio_get_rawdata, mkpio_get_rawdata_level + use mkpioMod , only : mkpio_iodesc_output, mkpio_iodesc_rawdata, mkpio_put_time_slice + use mkesmfMod , only : regrid_rawdata, create_routehandle_r8, get_meshareas + use mkutilsMod , only : chkerr + use mkpftConstantsMod , only : c3cropindex, c3irrcropindex + use mkvarctl , only : root_task, ndiag, outnc_double, numpft, mpicom + + implicit none + private + +#include + + public :: mklai + private :: check_global_sums + + character(len=*) , parameter :: u_FILE_u = & + __FILE__ + +!================================================================================= +contains +!================================================================================= + + subroutine mklai(file_mesh_i, file_data_i, mesh_o, pioid_o, rc) + ! + ! Make LAI/SAI/height data + ! + ! input/output variables + character(len=*) , intent(in) :: file_mesh_i ! input mesh file name + character(len=*) , intent(in) :: file_data_i ! input data file name + type(ESMF_Mesh) , intent(in) :: mesh_o ! output mesh + type(file_desc_t) , intent(inout) :: pioid_o + integer , intent(out) :: rc + ! + ! local variables + type(ESMF_RouteHandle) :: routehandle ! nearest neighbor routehandle + type(ESMF_Mesh) :: mesh_i + type(file_desc_t) :: pioid_i + type(io_desc_t) :: pio_iodesc_i + type(io_desc_t) :: pio_iotype_i + type(var_desc_t) :: pio_varid_i + integer :: pio_vartype_i + type(io_desc_t) :: pio_iodesc_o + type(var_desc_t) :: pio_varid_o + integer :: dimid + integer :: ni,no + integer :: ns_i, ns_o + integer :: k,l,m,nt ! indices + integer :: numpft_i ! number of plant types on input + integer :: ntime ! number of input time samples + integer , allocatable :: mask_i(:) + real(r8), allocatable :: frac_i(:) + real(r8), allocatable :: frac_o(:) + real(r8), allocatable :: data_i(:,:) + real(r8), allocatable :: data_o(:,:) + real(r8), allocatable :: mlai_o(:,:) ! monthly lai + real(r8), allocatable :: msai_o(:,:) ! monthly sai + real(r8), allocatable :: mhgtt_o(:,:) ! monthly height (top) + real(r8), allocatable :: mhgtb_o(:,:) ! monthly height (bottom) + integer, allocatable :: laimask(:,:) ! lai+sai output mask for each plant function type + real(r8), allocatable :: area_i(:) + real(r8), allocatable :: area_o(:) + integer :: ier, rcode ! error status + integer :: xtype ! external type + character(len=*), parameter :: subname = 'mklai' + !----------------------------------------------------------------------- + + rc = ESMF_SUCCESS + + if (root_task) then + write(ndiag,*) + write(ndiag,'(a)') 'Attempting to make LAIs/SAIs/heights .....' + write(ndiag,'(a)') ' Input file is '//trim(file_data_i) + write(ndiag,'(a)') ' Input mesh file is '//trim(file_mesh_i) + end if + + ! Open input data file + rcode = pio_openfile(pio_iosystem, pioid_i, pio_iotype, trim(file_data_i), pio_nowrite) + + ! Read in input mesh + call ESMF_VMLogMemInfo("Before create mesh_i in "//trim(subname)) + mesh_i = ESMF_MeshCreate(filename=trim(file_mesh_i), fileformat=ESMF_FILEFORMAT_ESMFMESH, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After create mesh_i in "//trim(subname)) + + ! Determine ns_i + call ESMF_MeshGet(mesh_i, numOwnedElements=ns_i, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Determine ns_o + call ESMF_MeshGet(mesh_o, numOwnedElements=ns_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Get the landmask from the input data file and reset the mesh mask based on that + allocate(frac_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort() + allocate(mask_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort() + call mkpio_get_rawdata(pioid_i, 'LANDMASK', mesh_i, frac_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + do ni = 1,ns_i + if (frac_i(ni) > 0._r8) then + mask_i(ni) = 1 + else + mask_i(ni) = 0 + end if + end do + deallocate(frac_i) + call ESMF_MeshSet(mesh_i, elementMask=mask_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! Create a route handle between the input and output mesh + allocate(frac_o(ns_o)) + call create_routehandle_r8(mesh_i=mesh_i, mesh_o=mesh_o, norm_by_fracs=.true., & + routehandle=routehandle, frac_o=frac_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After create routehandle in "//trim(subname)) + + rcode = pio_inq_dimid(pioid_i, 'pft', dimid) + rcode = pio_inq_dimlen(pioid_i, dimid, numpft_i) + rcode = pio_inq_dimid(pioid_i, 'time', dimid) + rcode = pio_inq_dimlen(pioid_i, dimid, ntime) + + if (numpft_i /= numpft+1) then + if (root_task) then + write(ndiag,*) 'WARNING: ' // trim(subname) // '(): parameter numpft+1 = ', numpft+1, & + 'does not equal input dataset numpft = ', numpft_i + write(ndiag,*)'This inconsistency used to stop the program. Now we allow it ' + write(ndiag,*)'because crop pfts 17-last are assumed to never use satellite lai data.' + end if + if (numpft_i > numpft + 1) then + ! NOTE(bja, 2015-01) If this error check is determined to be + ! invalid, all the loop bounds over output data in this + ! routine will need to be double checked! + if (root_task) then + write(ndiag,*) (subname) //' error input numpft must be less than or equal to output numpft+1.' + end if + call shr_sys_abort() + end if + endif + if (ntime /= 12) then + if (root_task) then + write(ndiag,*) subname // 'error must have 12 time samples on input data' + end if + call shr_sys_abort() + endif + + ! Dynamic allocation of variables of size 0:numpft + allocate(mlai_o(ns_o,0:numpft), & + msai_o(ns_o,0:numpft), & + mhgtt_o(ns_o,0:numpft), & + mhgtb_o(ns_o,0:numpft), & + laimask(ns_i,0:numpft), stat=ier ) + if (ier /= 0) then + call shr_sys_abort(subname //' mklai allocation error ') + end if + + ! Create iodescriptor for a single level of the input data + call mkpio_iodesc_rawdata(mesh_i, 'MONTHLY_LAI', pioid_i, pio_varid_i, pio_vartype_i, pio_iodesc_i, rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! Create iodescriptor for a single level of the output data + call mkpio_iodesc_output(pioid_o, mesh_o, 'MONTHLY_LAI', pio_iodesc_o, rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in generating an iodesc for MONTHLY_LAI') + + ! Allocate memory that will be used in time loop below + allocate(data_i(0:numpft_i,ns_i),stat=ier) + if (ier/=0) call shr_sys_abort() + allocate(data_o(0:numpft_i,ns_o),stat=ier) + if (ier/=0) call shr_sys_abort() + + ! The following is needed for the global check + allocate(area_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort() + allocate(area_o(ns_o), stat=ier) + if (ier/=0) call shr_sys_abort() + call get_meshareas(mesh_i, area_i, rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call get_meshareas(mesh_o, area_o, rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! Loop over the 12 months and write out data + mlai_o(:,:) = 0. + msai_o(:,:) = 0. + mhgtt_o(:,:) = 0. + mhgtb_o(:,:) = 0. + + do nt = 1, ntime + + ! time is months for LAI, SAI, and pft heights + rcode = pio_inq_varid(pioid_o, 'time', pio_varid_o) + rcode = pio_put_var(pioid_o, pio_varid_o, (/nt/), nt) + + ! Below - copy LAI, SAI, & heights from the C3 crop (pft15) + ! to the irrigated (pft16) whether crop is on or off + ! Hence loop to numpft_i - 1 for other pfts + + ! Read in one time slice of data for mlai, regrid and write out + rcode = pio_inq_varid(pioid_i, 'MONTHLY_LAI', pio_varid_i) + call pio_setframe(pioid_i, pio_varid_i, int(nt, kind=Pio_Offset_Kind)) + call mkpio_get_rawdata_level(pioid_i, pio_iodesc_i, nt, 'MONTHLY_LAI', data_i) + call regrid_rawdata(mesh_i, mesh_o, routehandle, data_i, data_o, 0, numpft_i, rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + do l = 0,numpft_i-1 + do no = 1,ns_o + mlai_o(no,l) = data_o(l,no) + end do + end do + mlai_o(:,c3irrcropindex) = mlai_o(:,c3cropindex) + rcode = pio_inq_varid(pioid_o, 'MONTHLY_LAI', pio_varid_o) + call mkpio_put_time_slice(pioid_o, pio_varid_o, pio_iodesc_o, nt, mlai_o) + call check_global_sums('LAI', ns_i, ns_o, numpft_i, nt, & + data_i, data_o, area_i, area_o, mask_i, frac_o) + + ! Read in one time slice of data for msai, regrid and write out + rcode = pio_inq_varid(pioid_i, 'MONTHLY_SAI', pio_varid_i) + call pio_setframe(pioid_i, pio_varid_i, int(nt, kind=Pio_Offset_Kind)) + call mkpio_get_rawdata_level(pioid_i, pio_iodesc_i, nt, 'MONTHLY_SAI', data_i) + call regrid_rawdata(mesh_i, mesh_o, routehandle, data_i, data_o, 0, numpft_i, rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + do l = 0,numpft_i-1 + do no = 1,ns_o + msai_o(no,l) = data_o(l,no) + end do + end do + msai_o(:,c3irrcropindex) = msai_o(:,c3cropindex) + rcode = pio_inq_varid(pioid_o, 'MONTHLY_SAI', pio_varid_o) + call mkpio_put_time_slice(pioid_o, pio_varid_o, pio_iodesc_o, nt, msai_o) + + ! Read in one time slice of data for msai, regrid and write out + rcode = pio_inq_varid(pioid_i, 'MONTHLY_HEIGHT_TOP', pio_varid_i) + call pio_setframe(pioid_i, pio_varid_i, int(nt, kind=Pio_Offset_Kind)) + call mkpio_get_rawdata_level(pioid_i, pio_iodesc_i, nt, 'MONTHLY_HEIGHT_TOP', data_i) + call regrid_rawdata(mesh_i, mesh_o, routehandle, data_i, data_o, 0, numpft_i, rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + do l = 0,numpft_i-1 + do no = 1,ns_o + mhgtt_o(no,l) = data_o(l,no) + end do + end do + mhgtt_o(:,c3irrcropindex) = mhgtt_o(:,c3cropindex) + rcode = pio_inq_varid(pioid_o, 'MONTHLY_HEIGHT_TOP', pio_varid_o) + call mkpio_put_time_slice(pioid_o, pio_varid_o, pio_iodesc_o, nt, mhgtt_o) + + ! Read in one time slice of data for msai, regrid and write out + rcode = pio_inq_varid(pioid_i, 'MONTHLY_HEIGHT_BOT', pio_varid_i) + call pio_setframe(pioid_i, pio_varid_i, int(nt, kind=Pio_Offset_Kind)) + call mkpio_get_rawdata_level(pioid_i, pio_iodesc_i, nt, 'MONTHLY_HEIGHT_BOT', data_i) + call regrid_rawdata(mesh_i, mesh_o, routehandle, data_i, data_o, 0, numpft_i, rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + do l = 0,numpft_i-1 + do no = 1,ns_o + mhgtb_o(no,l) = data_o(l,no) + end do + end do + mhgtb_o(:,c3irrcropindex) = mhgtb_o(:,c3cropindex) + rcode = pio_inq_varid(pioid_o, 'MONTHLY_HEIGHT_BOT', pio_varid_o) + call mkpio_put_time_slice(pioid_o, pio_varid_o, pio_iodesc_o, nt, mhgtb_o) + + if (root_task) then + write (ndiag,*) 'Successfully made LAIs/SAIs/heights for month ', nt + end if + + end do ! end loop over months + call pio_syncfile(pioid_o) + + ! Free the decomps and close the file + call pio_freedecomp(pioid_o, pio_iodesc_o) + call pio_freedecomp(pioid_i, pio_iodesc_i) + call pio_closefile(pioid_i) + call ESMF_VMLogMemInfo("After pio_closefile for input in "//trim(subname)) + + ! Release memory + call ESMF_RouteHandleDestroy(routehandle, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + call ESMF_MeshDestroy(mesh_i, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + call ESMF_VMLogMemInfo("After destroy operations in "//trim(subname)) + + end subroutine mklai + + !================================================================================= + subroutine check_global_sums(name, ns_i, ns_o, numpft_i, nt, & + data_i, data_o, area_i, area_o, mask_i, frac_o) + + ! Compare global areas on input and output grids + ! NB. data_i and data_o started at 0 outside this subroutine but start + ! at 1 within the subroutine, so the loops in the subroutine start at 1 + + ! input/otuput variables + character(len=*) , intent(in) :: name + integer , intent(in) :: ns_i + integer , intent(in) :: ns_o + integer , intent(in) :: nt + integer , intent(in) :: numpft_i + real(r8) , intent(in) :: data_i(:,:) + real(r8) , intent(in) :: data_o(:,:) + real(r8) , intent(in) :: area_i(:) + real(r8) , intent(in) :: area_o(:) + integer , intent(in) :: mask_i(:) + real(r8) , intent(in) :: frac_o(:) + + ! local variables + integer :: ni, no, l, k + integer :: ier + real(r8) :: local_i(numpft_i) ! local global area, by surface type + real(r8) :: local_o(numpft_i) ! local global area, by surface type + real(r8) :: global_i(numpft_i) ! input grid: global area pfts + real(r8) :: global_o(numpft_i) ! output grid: global area pfts + !----------------------------------------------------------------------- + + ! Input grid global area + local_i(:) = 0. + do l = 1, numpft_i + do ni = 1, ns_i + local_i(l) = local_i(l) + data_i(l,ni) *area_i(ni)*mask_i(ni) + end do + end do + call mpi_reduce(local_i, global_i , numpft_i, MPI_REAL8, MPI_SUM, 0, mpicom, ier) + + ! Output grid global area + local_o(:) = 0. + do l = 1, numpft_i + do no = 1, ns_o + local_o(l) = local_o(l) + data_o(l,no) *area_o(no)*frac_o(no) + end do + end do + call mpi_reduce(local_o, global_o , numpft_i, MPI_REAL8, MPI_SUM, 0, mpicom, ier) + + ! Comparison + if (root_task) then + write (ndiag,*) + write (ndiag,*) trim(name)//' Output for month ',nt + write (ndiag,'(1x,70a1)') ('.',k=1,70) + write (ndiag,101) +101 format (1x,'PFT input grid area output grid area',/ & + 1x,3x,' 10**6 km**2',' 10**6 km**2') + write (ndiag,'(1x,70a1)') ('.',k=1,70) + write (ndiag,*) + do l = 1, numpft_i + write (ndiag,102) l-1, global_i(l)*1.e-06*1.e-02, global_o(l)*1.e-06*1.e-02 +102 format (1x,i3,f16.3,f17.3) + end do + end if + + end subroutine check_global_sums + +end module mklaiMod diff --git a/tools/mksurfdata_esmf/src/mklanwatMod.F90 b/tools/mksurfdata_esmf/src/mklanwatMod.F90 new file mode 100644 index 0000000000..b4160a830c --- /dev/null +++ b/tools/mksurfdata_esmf/src/mklanwatMod.F90 @@ -0,0 +1,476 @@ +module mklanwatMod + + !----------------------------------------------------------------------- + ! make %lake and %wetland from input lake / wetland data + ! also make lake parameters + !----------------------------------------------------------------------- + + use ESMF + use pio , only : file_desc_t, pio_openfile, pio_closefile, pio_nowrite, pio_syncfile + use shr_kind_mod , only : r8 => shr_kind_r8, r4 => shr_kind_r4 + use shr_sys_mod , only : shr_sys_abort + use mkpioMod , only : mkpio_get_rawdata, pio_iotype, pio_iosystem + use mkesmfMod , only : regrid_rawdata, create_routehandle_r8 + use mkdiagnosticsMod , only : output_diagnostics_continuous, output_diagnostics_area + use mkchecksMod , only : min_bad + use mkutilsMod , only : chkerr + use mkvarctl , only : root_task, ndiag, spval, no_inlandwet + use mkfileMod , only : mkfile_output + + implicit none + private + + public :: mkpctlak ! make %lake + public :: mklakdep ! make lake depth + public :: mkwetlnd ! make %wetland + public :: update_max_array_lake ! Update the maximum lake percent + + real(r8), allocatable :: frac_o_mklak_nonorm(:) + type(ESMF_RouteHandle) :: routehandle_mklak_nonorm + + character(len=*) , parameter :: u_FILE_u = & + __FILE__ + +!=============================================================== +contains +!=============================================================== + + subroutine mkpctlak(file_mesh_i, file_data_i, mesh_o, lake_o, pioid_o, rc) + + ! ------------------- + ! make %lake + ! PCT_LAKE is written to fsurdat in mksurfdata after adjustments are made + ! ------------------- + + ! uses + use mkinputMod, only: mksrf_fdynuse + + ! input/output variables + character(len=*) , intent(in) :: file_mesh_i ! input mesh file name + character(len=*) , intent(in) :: file_data_i ! input data file name + type(ESMF_Mesh) , intent(in) :: mesh_o + type(file_desc_t) , intent(inout) :: pioid_o + real(r8) , intent(out) :: lake_o(:) ! output grid: %lake + integer , intent(out) :: rc + + ! local variables + type(ESMF_Mesh) :: mesh_i + type(file_desc_t) :: pioid_i + integer , allocatable :: mask_i(:) + real(r8), allocatable :: rmask_i(:) + real(r8), allocatable :: lake_i(:) ! input grid: percent lake + integer :: ni,no,k ! indices + integer :: ns_i,ns_o ! local sizes + integer :: ier,rcode ! error status + character(len=*), parameter :: subname = ' mkpctlak ' + !----------------------------------------------------------------------- + + rc = ESMF_SUCCESS + + if (root_task) then + write(ndiag,*) + write(ndiag,'(1x,80a1)') ('=',k=1,80) + write(ndiag,*) + write(ndiag,'(a)')'Attempting to make %lake' + write(ndiag,'(a)') ' Input file is '//trim(file_data_i) + write(ndiag,'(a)') ' Input mesh file is '//trim(file_mesh_i) + end if + + ! ---------------------------------------- + ! Read i input data and input mesh and create route handle + ! ---------------------------------------- + + ! Open raw data file + rcode = pio_openfile(pio_iosystem, pioid_i, pio_iotype, trim(file_data_i), pio_nowrite) + + ! Read in input mesh + mesh_i = ESMF_MeshCreate(filename=trim(file_mesh_i), fileformat=ESMF_FILEFORMAT_ESMFMESH, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After create mesh_i in "//trim(subname)) + + ! Determine ns_i + call ESMF_MeshGet(mesh_i, numOwnedElements=ns_i, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Determine ns_o + call ESMF_MeshGet(mesh_o, numOwnedElements=ns_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Get the landmask from the input data file and reset the mesh mask based on that + allocate(rmask_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort() + allocate(mask_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort() + call mkpio_get_rawdata(pioid_i, 'LANDMASK', mesh_i, rmask_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + do ni = 1,ns_i + if (rmask_i(ni) > 0._r8) then + mask_i(ni) = 1 + else + mask_i(ni) = 0 + end if + end do + call ESMF_MeshSet(mesh_i, elementMask=mask_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! Create a route handle between the input and output mesh + if (.not. ESMF_RouteHandleIsCreated(routehandle_mklak_nonorm)) then + allocate(frac_o_mklak_nonorm(ns_o)) + ! Note that norm_by_fracs is false in the following because this routehandle is + ! used to map fields that are expressed in terms of % of the grid cell. + call create_routehandle_r8(mesh_i=mesh_i, mesh_o=mesh_o, norm_by_fracs=.false., & + routehandle=routehandle_mklak_nonorm, frac_o=frac_o_mklak_nonorm, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After create routehandle in "//trim(subname)) + end if + + ! ---------------------------------------- + ! Create %lake + ! ---------------------------------------- + + lake_o(:) = 0._r8 + if (root_task) then + write (ndiag,*) 'Attempting to make %lake .....' + end if + + ! Read in lake_i + allocate(lake_i(ns_i), stat=rcode) + if (rcode/=0) call shr_sys_abort() + call mkpio_get_rawdata(pioid_i, 'PCT_LAKE', mesh_i, lake_i, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Regrid lake_i to lake_o + call regrid_rawdata(mesh_i, mesh_o, routehandle_mklak_nonorm, lake_i, lake_o, rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + do no = 1,ns_o + if (lake_o(no) < 1.) lake_o(no) = 0. + enddo + + ! Check global areas + call output_diagnostics_area(mesh_i, mesh_o, mask_i, frac_o_mklak_nonorm, & + lake_i, lake_o, "pct lake", percent=.true., ndiag=ndiag, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + deallocate (lake_i) + + ! ---------------------------------------- + ! Wrap things up + ! ---------------------------------------- + + call pio_closefile(pioid_i) + + ! Release memory + if (mksrf_fdynuse == ' ') then ! ...else we will reuse it + deallocate(frac_o_mklak_nonorm) + call ESMF_RouteHandleDestroy(routehandle_mklak_nonorm, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + end if + call ESMF_MeshDestroy(mesh_i, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + + if (root_task) then + write (ndiag,*) 'Successfully made %lake' + end if + call ESMF_VMLogMemInfo("At end of "//trim(subname)) + + end subroutine mkpctlak + +!=============================================================== + subroutine mklakdep(file_mesh_i, file_data_i, mesh_o, pioid_o, fsurdat, rc) + + ! ------------------- + ! make lake depth + ! LAKE_DEPTH is written out to fsurdat here + ! ------------------- + + ! uses + + ! input/output variables + character(len=*) , intent(in) :: file_mesh_i ! input mesh file name + character(len=*) , intent(in) :: file_data_i ! input data file name + type(ESMF_Mesh) , intent(in) :: mesh_o + type(file_desc_t) , intent(inout) :: pioid_o + character(len=*) , intent(in) :: fsurdat + integer , intent(out) :: rc + + ! local variables + type(ESMF_Mesh) :: mesh_i + type(ESMF_RouteHandle) :: routehandle + type(file_desc_t) :: pioid_i + integer , allocatable :: mask_i(:) + real(r8), allocatable :: rmask_i(:) + real(r8), allocatable :: frac_o(:) + real(r8), allocatable :: lakedepth_i(:) ! iput grid: lake depth (m) + real(r8), allocatable :: lakedepth_o(:) ! output grid: lake depth (m) + integer :: ni,no,k ! indices + integer :: ns_i,ns_o ! local sizes + integer :: ier,rcode ! error status + real(r8), parameter :: min_valid_lakedepth = 0._r8 + character(len=*), parameter :: subname = ' mklakdep ' + !----------------------------------------------------------------------- + + rc = ESMF_SUCCESS + + if (root_task) then + write(ndiag,*) + write(ndiag,'(1x,80a1)') ('=',k=1,80) + write(ndiag,*) + write(ndiag,'(a)')'Attempting to make lake depth' + write(ndiag,'(a)') ' Input file is '//trim(file_data_i) + write(ndiag,'(a)') ' Input mesh file is '//trim(file_mesh_i) + end if + + ! ---------------------------------------- + ! Read i input data and input mesh and create route handle + ! ---------------------------------------- + + ! Open raw data file + rcode = pio_openfile(pio_iosystem, pioid_i, pio_iotype, trim(file_data_i), pio_nowrite) + + ! Read in input mesh + mesh_i = ESMF_MeshCreate(filename=trim(file_mesh_i), fileformat=ESMF_FILEFORMAT_ESMFMESH, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After create mesh_i in "//trim(subname)) + + ! Determine ns_i + call ESMF_MeshGet(mesh_i, numOwnedElements=ns_i, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Determine ns_o + call ESMF_MeshGet(mesh_o, numOwnedElements=ns_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Get the landmask from the input data file and reset the mesh mask based on that + allocate(rmask_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort() + allocate(mask_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort() + call mkpio_get_rawdata(pioid_i, 'LANDMASK', mesh_i, rmask_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + do ni = 1,ns_i + if (rmask_i(ni) > 0._r8) then + mask_i(ni) = 1 + else + mask_i(ni) = 0 + end if + end do + call ESMF_MeshSet(mesh_i, elementMask=mask_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! Create a route handle between the input and output mesh + allocate(frac_o(ns_o)) + call create_routehandle_r8(mesh_i=mesh_i, mesh_o=mesh_o, norm_by_fracs=.true., & + routehandle=routehandle, frac_o=frac_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After create routehandle in "//trim(subname)) + + ! ---------------------------------------- + ! Create lake parameter (lakedepth) + ! ---------------------------------------- + + if (root_task) then + write (ndiag,*) 'Attempting to make lake depth .....' + end if + + ! lakedepth + allocate(lakedepth_i(ns_i), stat=rcode) + if (rcode/=0) call shr_sys_abort() + call mkpio_get_rawdata(pioid_i, 'LAKEDEPTH', mesh_i, lakedepth_i, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! regrid lakedepth_i to lakedepth_o - this also returns lakedepth_i to be used in the global sums below + allocate (lakedepth_o(ns_o)); lakedepth_o(:) = spval + call regrid_rawdata(mesh_i, mesh_o, routehandle, lakedepth_i, lakedepth_o, rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After regrid_rawdata for lakedepth in "//trim(subname)) + do no = 1,ns_o + if (frac_o(no) == 0._r8) then + lakedepth_o(no) = 10._r8 + end if + enddo + if (min_bad(lakedepth_o, min_valid_lakedepth, 'lakedepth')) then + call shr_sys_abort() + end if + + if (fsurdat /= ' ') then + if (root_task) write(ndiag, '(a)') trim(subname)//" writing out lakedepth" + call mkfile_output(pioid_o, mesh_o, 'LAKEDEPTH', lakedepth_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkfile_output') + call pio_syncfile(pioid_o) + end if + + ! Check global areas for lake depth + call output_diagnostics_continuous(mesh_i, mesh_o, & + lakedepth_i, lakedepth_o, "lake depth", "m", & + ndiag=ndiag, rc=rc, mask_i=mask_i, frac_o=frac_o) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! ---------------------------------------- + ! Wrap things up + ! ---------------------------------------- + + call pio_closefile(pioid_i) + + ! Release memory + deallocate(frac_o) + call ESMF_RouteHandleDestroy(routehandle, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + call ESMF_MeshDestroy(mesh_i, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + + if (root_task) then + write (ndiag,*) 'Successfully made lake depth' + end if + call ESMF_VMLogMemInfo("At end of "//trim(subname)) + + end subroutine mklakdep + +!=============================================================== + subroutine mkwetlnd(file_mesh_i, file_data_i, mesh_o, swmp_o, rc) + + ! ---------------------------------------- + ! Create %wetland + ! Note PCT_WETLAND is written out of mksurfdata after adjustments are made + ! ---------------------------------------- + + ! input/output variables + character(len=*) , intent(in) :: file_mesh_i ! input mesh file name + character(len=*) , intent(in) :: file_data_i ! input data file name + type(ESMF_Mesh) , intent(in) :: mesh_o + real(r8) , intent(out) :: swmp_o(:) ! output grid: %lake + integer , intent(out) :: rc + + ! local variables + type(ESMF_RouteHandle) :: routehandle_nonorm + type(ESMF_Mesh) :: mesh_i + type(file_desc_t) :: pioid_i + integer , allocatable :: mask_i(:) + real(r8), allocatable :: rmask_i(:) + real(r8), allocatable :: frac_o_nonorm(:) + real(r8), allocatable :: swmp_i(:) ! input grid: percent wetland + integer :: ni,no,k ! indices + integer :: ns_i,ns_o ! local sizes + integer :: ier,rcode ! error status + character(len=*), parameter :: subname = ' mkwetlnd ' + !----------------------------------------------------------------------- + + rc = ESMF_SUCCESS + + if ( no_inlandwet) then + if (root_task) then + write (ndiag,*) 'Attempting to make %wetland .....' + if (root_task) write(ndiag, '(a)') trim(subname)//" setting PCT_WETLAND to zero" + end if + swmp_o(:) = 0._r8 + RETURN + end if + + if (root_task) then + write(ndiag,*) 'Attempting to make %wetland .....' + write(ndiag,'(a)') ' Input file is '//trim(file_data_i) + write(ndiag,'(a)') ' Input mesh file is '//trim(file_mesh_i) + end if + + ! Open input data file + rcode = pio_openfile(pio_iosystem, pioid_i, pio_iotype, trim(file_data_i), pio_nowrite) + + ! Read in input mesh + mesh_i = ESMF_MeshCreate(filename=trim(file_mesh_i), fileformat=ESMF_FILEFORMAT_ESMFMESH, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After create mesh_i in "//trim(subname)) + + ! Determine ns_i + call ESMF_MeshGet(mesh_i, numOwnedElements=ns_i, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Determine ns_o + call ESMF_MeshGet(mesh_o, numOwnedElements=ns_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Get the landmask from the input data file and reset the mesh mask based on that + allocate(rmask_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort() + allocate(mask_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort() + call mkpio_get_rawdata(pioid_i, 'LANDMASK', mesh_i, rmask_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + do ni = 1,ns_i + if (rmask_i(ni) > 0._r8) then + mask_i(ni) = 1 + else + mask_i(ni) = 0 + end if + end do + call ESMF_MeshSet(mesh_i, elementMask=mask_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! Create a route handle between the input and output mesh + allocate(frac_o_nonorm(ns_o)) + ! Note that norm_by_fracs is false in the following because this routehandle is + ! used to map fields that are expressed in terms of % of the grid cell. + call create_routehandle_r8(mesh_i=mesh_i, mesh_o=mesh_o, norm_by_fracs=.false., & + routehandle=routehandle_nonorm, frac_o=frac_o_nonorm, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After create routehandle in "//trim(subname)) + + ! read in swmp_i + allocate(swmp_i(ns_i), stat=rcode) + if (rcode/=0) call shr_sys_abort() + call mkpio_get_rawdata(pioid_i, 'PCT_WETLAND', mesh_i, swmp_i, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! regrid swmp_i to swmp_o - this also returns swmp_i to be used in the global sums below + call regrid_rawdata(mesh_i, mesh_o, routehandle_nonorm, swmp_i, swmp_o, rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After regrid_data for wetland") + if (ChkErr(rc,__LINE__,u_FILE_u)) return + do no = 1,ns_o + if (swmp_o(no) < 1.) swmp_o(no) = 0. + enddo + + ! Check global areas + call output_diagnostics_area(mesh_i, mesh_o, mask_i, frac_o_nonorm, & + swmp_i, swmp_o, "pct wetland", percent=.true., ndiag=ndiag, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Close the single input data file + call pio_closefile(pioid_i) + + ! Release memory + call ESMF_RouteHandleDestroy(routehandle_nonorm, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + call ESMF_MeshDestroy(mesh_i, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + + if (root_task) then + write (ndiag,*) 'Successfully made %wetland' + end if + call ESMF_VMLogMemInfo("At end of "//trim(subname)) + + end subroutine mkwetlnd + +!=============================================================== +subroutine update_max_array_lake(pct_lakmax_arr,pct_lake_arr) + ! + ! !DESCRIPTION: + ! Update the maximum lake percent for landuse.timeseries file + ! + ! !ARGUMENTS: + real(r8) , intent(inout):: pct_lakmax_arr(:) ! max lake percent + real(r8) , intent(in):: pct_lake_arr(:) ! lake percent that is used to update the old pct_lakmax_arr + ! + ! !LOCAL VARIABLES: + integer :: n,ns ! indices + + character(len=*), parameter :: subname = 'update_max_array_lake' + !----------------------------------------------------------------------- + ns = size(pct_lake_arr,1) + do n = 1, ns + if (pct_lake_arr(n) > pct_lakmax_arr(n)) then + pct_lakmax_arr(n) = pct_lake_arr(n) + end if + end do + +end subroutine update_max_array_lake + +end module mklanwatMod diff --git a/tools/mksurfdata_map/src/mkpctPftTypeMod.F90 b/tools/mksurfdata_esmf/src/mkpctPftTypeMod.F90 similarity index 86% rename from tools/mksurfdata_map/src/mkpctPftTypeMod.F90 rename to tools/mksurfdata_esmf/src/mkpctPftTypeMod.F90 index 8c2c9b7c53..b52a2754b3 100644 --- a/tools/mksurfdata_map/src/mkpctPftTypeMod.F90 +++ b/tools/mksurfdata_esmf/src/mkpctPftTypeMod.F90 @@ -1,27 +1,17 @@ module mkpctPftTypeMod !----------------------------------------------------------------------- - !BOP - ! - ! !MODULE: mkpctPftType - ! - ! !DESCRIPTION: ! Derived type and associated methods for operating on pct_pft data - ! - ! !REVISION HISTORY: - ! Author: Bill Sacks - ! !----------------------------------------------------------------------- - !!USES: use shr_kind_mod, only : r8 => shr_kind_r8 + use shr_sys_mod , only : shr_sys_abort implicit none private - ! !PUBLIC TYPES public :: pct_pft_type - + type :: pct_pft_type private real(r8), allocatable :: pct_p2l(:) ! pct of each pft on the landunit @@ -45,8 +35,7 @@ module mkpctPftTypeMod procedure, private :: check_vals ! perform a sanity check after setting values end type pct_pft_type - ! !PUBLIC MEMBER FUNCTIONS - public :: update_max_array ! given an array of pct_pft_type variables update the max_p2l values from pct_p2l + public :: update_max_array ! given an array of pct_pft_type variables update the max_p2l values from pct_p2l public :: get_pct_p2l_array ! given an array of pct_pft_type variables, return a 2-d array of pct_p2l public :: get_pct_l2g_array ! given an array of pct_pft_type variables, return an array of pct_l2g @@ -56,13 +45,12 @@ module mkpctPftTypeMod module procedure constructor_empty ! initialize a new pct_pft_type object for an empty landunit end interface pct_pft_type - ! !PRIVATE TYPES: real(r8), parameter :: tol = 1.e-12_r8 ! tolerance for checking equality - !EOP - +!=============================================================== contains - +!=============================================================== + ! ======================================================================== ! Constructors ! ======================================================================== @@ -70,7 +58,6 @@ module mkpctPftTypeMod !----------------------------------------------------------------------- function constructor_pong(pct_p2g, first_pft_index, default_pct_p2l) result(this) ! - ! !DESCRIPTION: ! Given the % of each pft on the grid cell, create a pct_pft_type object. ! ! Note that pct_p2g should just contain the pfts in this landunit. @@ -80,22 +67,20 @@ function constructor_pong(pct_p2g, first_pft_index, default_pct_p2l) result(this ! (1) size of default_pct_p2l must match size of pct_p2g ! (2) default_pct_p2l must sum to 100% ! - ! !ARGUMENTS: - type(pct_pft_type) :: this ! function result - + ! input/output variables + type(pct_pft_type) :: this ! function result real(r8), intent(in) :: pct_p2g(:) ! % of each pft on the grid cell integer , intent(in) :: first_pft_index ! index of the first pft (lower bound of arrays) real(r8), intent(in) :: default_pct_p2l(:) ! default % of each pft on the landunit, used if total landunit area is 0% ! - ! !LOCAL VARIABLES: + ! local variables integer :: last_pft_index - character(len=*), parameter :: subname = 'constructor_pong' !----------------------------------------------------------------------- if (size(default_pct_p2l) /= size(pct_p2g)) then write(6,*) subname//' ERROR: size of default_pct_p2l must match size of pct_p2g' - call abort() + call shr_sys_abort() end if last_pft_index = first_pft_index + size(pct_p2g) - 1 @@ -107,22 +92,19 @@ end function constructor_pong !----------------------------------------------------------------------- function constructor(pct_p2l, pct_l2g, first_pft_index) result(this) ! - ! !DESCRIPTION: - ! Given the % of each pft on the land cell and % of land unit on grid cell, + ! Given the % of each pft on the land cell and % of land unit on grid cell, ! create a pct_pft_type object. ! ! Note that pct_p2g should just contain the pfts in this landunit. ! - ! !ARGUMENTS: + ! input/output variables type(pct_pft_type) :: this ! function result - real(r8), intent(in) :: pct_p2l(:) ! % of each pft on the landunit real(r8), intent(in) :: pct_l2g ! % of the landunit on the grid cell integer , intent(in) :: first_pft_index ! index of the first pft (lower bound of arrays) ! - ! !LOCAL VARIABLES: + ! local variables integer :: last_pft_index - character(len=*), parameter :: subname = 'constructor' !----------------------------------------------------------------------- @@ -136,26 +118,22 @@ end function constructor !----------------------------------------------------------------------- function constructor_empty() result(this) ! - ! !DESCRIPTION: ! Initialize a new pct_pft_type object for an empty landunit - that is, one that has ! no PFTs on it, and never can (e.g., the crop landunit when we're running without ! prognostic crops, so that the landunit is always empty). ! - ! !ARGUMENTS: + ! input/output variables type(pct_pft_type) :: this ! function result ! - ! !LOCAL VARIABLES: - + ! local variables: character(len=*), parameter :: subname = 'constructor_empty' !----------------------------------------------------------------------- - + this%pct_l2g = 0._r8 allocate(this%pct_p2l(0)) end function constructor_empty - - ! ======================================================================== ! Public member functions ! ======================================================================== @@ -163,18 +141,16 @@ end function constructor_empty !----------------------------------------------------------------------- function get_pct_p2l(this) result(pct_p2l) ! - ! !DESCRIPTION: ! Get an array holding % of each pft on the landunit ! - ! !ARGUMENTS: + ! input/output variables class(pct_pft_type), intent(in) :: this real(r8) :: pct_p2l(size(this%pct_p2l)) ! function result ! - ! !LOCAL VARIABLES: - + ! local variables: character(len=*), parameter :: subname = 'get_pct_p2l' !----------------------------------------------------------------------- - + pct_p2l = this%pct_p2l end function get_pct_p2l @@ -182,18 +158,16 @@ end function get_pct_p2l !----------------------------------------------------------------------- function get_pct_p2g(this) result(pct_p2g) ! - ! !DESCRIPTION: ! Get an array holding % of each pft on the gridcell ! - ! !ARGUMENTS: + ! input/output variables class(pct_pft_type), intent(in) :: this real(r8) :: pct_p2g(size(this%pct_p2l)) ! function result ! - ! !LOCAL VARIABLES: - + ! local variables: character(len=*), parameter :: subname = 'get_pct_p2g' !----------------------------------------------------------------------- - + pct_p2g(:) = this%pct_p2l(:) * this%pct_l2g / 100._r8 end function get_pct_p2g @@ -201,18 +175,16 @@ end function get_pct_p2g !----------------------------------------------------------------------- function get_pct_l2g(this) result(pct_l2g) ! - ! !DESCRIPTION: ! Get % of landunit on the grid cell ! - ! !ARGUMENTS: + ! input/output variables real(r8) :: pct_l2g ! function result class(pct_pft_type), intent(in) :: this ! - ! !LOCAL VARIABLES: - + ! local variables: character(len=*), parameter :: subname = 'get_pct_l2g' !----------------------------------------------------------------------- - + pct_l2g = this%pct_l2g end function get_pct_l2g @@ -220,18 +192,16 @@ end function get_pct_l2g !----------------------------------------------------------------------- function get_first_pft_index(this) result(first_pft_index) ! - ! !DESCRIPTION: ! Get index of the first pft (lower bound of arrays) ! - ! !ARGUMENTS: + ! input/output variables integer :: first_pft_index ! function result class(pct_pft_type), intent(in) :: this ! - ! !LOCAL VARIABLES: - + ! local variables: character(len=*), parameter :: subname = 'get_first_pft_index' !----------------------------------------------------------------------- - + first_pft_index = lbound(this%pct_p2l, 1) end function get_first_pft_index @@ -239,19 +209,17 @@ end function get_first_pft_index !----------------------------------------------------------------------- function get_one_pct_p2g(this, pft_index) result(pct_p2g) ! - ! !DESCRIPTION: ! Get % of gridcell for a single pft ! - ! !ARGUMENTS: + ! input/output variables real(r8) :: pct_p2g ! function result class(pct_pft_type), intent(in) :: this integer :: pft_index ! - ! !LOCAL VARIABLES: - + ! local variables: character(len=*), parameter :: subname = 'get_one_pct_p2g' !----------------------------------------------------------------------- - + pct_p2g = this%pct_p2l(pft_index) * this%pct_l2g / 100._r8 end function get_one_pct_p2g @@ -259,22 +227,20 @@ end function get_one_pct_p2g !----------------------------------------------------------------------- subroutine set_pct_l2g(this, pct_l2g_new) ! - ! !DESCRIPTION: ! Set percent of landunit on the grid cell. Keep pct_p2l the same as before. ! - ! !ARGUMENTS: + ! input/output variables class(pct_pft_type), intent(inout) :: this real(r8), intent(in) :: pct_l2g_new ! new percent of this landunit with respect to grid cell ! - ! !LOCAL VARIABLES: - + ! local variables: character(len=*), parameter :: subname = 'set_pct_l2g' !----------------------------------------------------------------------- - + if (pct_l2g_new < 0._r8 .or. pct_l2g_new > (100._r8 + tol)) then write(6,*) subname//' ERROR: pct_l2g_new must be between 0 and 100%' write(6,*) 'pct_l2g_new = ', pct_l2g_new - call abort() + call shr_sys_abort() end if this%pct_l2g = pct_l2g_new @@ -284,7 +250,6 @@ end subroutine set_pct_l2g !----------------------------------------------------------------------- subroutine set_one_pct_p2g(this, pft_index, pct_p2g_new) ! - ! !DESCRIPTION: ! Set percent pft for a single pft, given its weight on the grid cell. ! ! The landunit percent is adjusted appropriately. In addition, the coverage of other @@ -295,24 +260,23 @@ subroutine set_one_pct_p2g(this, pft_index, pct_p2g_new) ! ! Note about pft_index: Note that the first element of the array has index given by ! the first_pft_index value given to the constructor. - ! - ! !ARGUMENTS: + ! + ! input/output variables class(pct_pft_type), intent(inout) :: this integer , intent(in) :: pft_index ! index of the pft to change - real(r8), intent(in) :: pct_p2g_new ! new percent of this pft, with respect to grid cell + real(r8), intent(in) :: pct_p2g_new ! new percent of this pft, with respect to grid cell ! - ! !LOCAL VARIABLES: + ! local variables: real(r8), allocatable :: pct_p2g(:) ! % of each pft on the grid cell - character(len=*), parameter :: subname = 'set_pct_p2g' !----------------------------------------------------------------------- - + if (pct_p2g_new < 0._r8 .or. pct_p2g_new > (100._r8 + tol)) then write(6,*) subname//' ERROR: pct_p2g_new must be between 0 and 100%' write(6,*) 'pct_p2g_new = ', pct_p2g_new - call abort() + call shr_sys_abort() end if - + allocate(pct_p2g(lbound(this%pct_p2l, 1) : ubound(this%pct_p2l, 1))) pct_p2g(:) = this%get_pct_p2g() pct_p2g(pft_index) = pct_p2g_new @@ -329,19 +293,17 @@ end subroutine set_one_pct_p2g !----------------------------------------------------------------------- subroutine merge_pfts(this, source, dest) ! - ! !DESCRIPTION: ! Merge all area from one PFT into another PFT ! - ! !ARGUMENTS: + ! input/output variables class(pct_pft_type), intent(inout) :: this integer, intent(in) :: source ! index of source PFT integer, intent(in) :: dest ! index of dest PFT ! - ! !LOCAL VARIABLES: - + ! local variables: character(len=*), parameter :: subname = 'merge_pfts' !----------------------------------------------------------------------- - + this%pct_p2l(dest) = this%pct_p2l(dest) + this%pct_p2l(source) this%pct_p2l(source) = 0._r8 @@ -352,18 +314,14 @@ end subroutine merge_pfts !----------------------------------------------------------------------- subroutine remove_small_cover(this, too_small, nsmall) ! - ! !DESCRIPTION: ! Remove any small PFTs, defined as those whose grid cell coverage is below some ! threshold. Also returns the number of small PFTs found. ! - ! !USES: - ! - ! !ARGUMENTS: + ! input/output variables class(pct_pft_type), intent(inout) :: this real(r8), intent(in) :: too_small ! threshold for considering a PFT too small (% of grid cell) integer , intent(out) :: nsmall ! number of small (but non-zero) PFTs found ! - ! !LOCAL VARIABLES: integer :: pft_lbound integer :: pft_ubound integer :: pft_index @@ -373,7 +331,7 @@ subroutine remove_small_cover(this, too_small, nsmall) character(len=*), parameter :: subname = 'remove_small_cover' !----------------------------------------------------------------------- - + pft_lbound = lbound(this%pct_p2l, 1) pft_ubound = ubound(this%pct_p2l, 1) allocate(pct_p2g (pft_lbound : pft_ubound)) @@ -383,7 +341,7 @@ subroutine remove_small_cover(this, too_small, nsmall) pct_p2g(:) = this%get_pct_p2g() is_zero(:) = (pct_p2g == 0._r8) is_small(:) = (pct_p2g < too_small .and. .not. is_zero(:)) - + nsmall = count(is_small(:)) if (nsmall > 0) then @@ -417,42 +375,40 @@ end subroutine remove_small_cover !----------------------------------------------------------------------- subroutine convert_from_p2g(this, pct_p2g, default_pct_p2l) ! - ! !DESCRIPTION: ! Given a p2g array, compute the p2l array and l2g ! - ! !ARGUMENTS: + ! input/output variables class(pct_pft_type), intent(inout) :: this real(r8), intent(in) :: pct_p2g(:) ! % of each pft on the grid cell real(r8), intent(in) :: default_pct_p2l(:) ! default % of each pft on the landunit, used if total landunit area is 0% ! - ! !LOCAL VARIABLES: - + ! local variables: character(len=*), parameter :: subname = 'convert_from_p2g' !----------------------------------------------------------------------- - + ! Check pre-conditions if (size(pct_p2g) /= size(this%pct_p2l) .or. size(default_pct_p2l) /= size(this%pct_p2l)) then write(6,*) subname//' ERROR: array size mismatch: ' write(6,*) size(pct_p2g), size(default_pct_p2l), size(this%pct_p2l) - call abort() + call shr_sys_abort() end if if (abs(sum(default_pct_p2l) - 100._r8) > tol) then write(6,*) subname//' ERROR: default_pct_p2l must sum to 100' - call abort() + call shr_sys_abort() end if if (any(pct_p2g < 0._r8)) then write(6,*) subname//' ERROR: negative values found in pct_p2g array' write(6,*) pct_p2g - call abort() + call shr_sys_abort() end if if (sum(pct_p2g) < 0._r8 .or. sum(pct_p2g) > (100._r8 + tol)) then write(6,*) subname//' ERROR: pct_p2g must be between 0 and 100' write(6,*) 'sum(pct_p2g) = ', sum(pct_p2g) - call abort() + call shr_sys_abort() end if ! Done checking pre-conditions @@ -474,77 +430,73 @@ end subroutine convert_from_p2g !----------------------------------------------------------------------- subroutine check_vals(this, caller) ! - ! !DESCRIPTION: ! Perform a sanity check after setting values ! - ! !ARGUMENTS: + ! input/output variables class(pct_pft_type), intent(in) :: this character(len=*), intent(in) :: caller ! name of the calling subroutine ! - ! !LOCAL VARIABLES: - + ! local variables: character(len=*), parameter :: subname = 'check_vals' !----------------------------------------------------------------------- - + if (abs(sum(this%pct_p2l) - 100._r8) > tol) then write(6,*) subname//' ERROR from ', caller, ': pct_p2l does not sum to 100' write(6,*) 'sum(this%pct_p2l) = ', sum(this%pct_p2l) - call abort() + call shr_sys_abort() end if if (any(this%pct_p2l < 0._r8)) then write(6,*) subname//' ERROR from ', caller, ': negative values found in pct_p2l' write(6,*) this%pct_p2l - call abort() + call shr_sys_abort() end if if (this%pct_l2g < 0._r8 .or. this%pct_l2g > (100._r8 + tol)) then write(6,*) subname//' ERROR from ', caller, ': pct_l2g must be between 0 and 100' write(6,*) 'pct_l2g = ', this%pct_l2g - call abort() + call shr_sys_abort() end if end subroutine check_vals - + ! ======================================================================== ! Module-level routines (not member functions) ! ======================================================================== !----------------------------------------------------------------------- - subroutine update_max_array(pct_pft_max_arr,pct_pft_arr) + subroutine update_max_array(pct_pft_max_arr, pct_pft_arr) ! - ! !DESCRIPTION: ! Given an array of pct_pft_type variables, update all the max_p2l variables. ! - ! Assumes that all elements of pct_pft_max_arr and pct_pft_arr have the same + ! Assumes that all elements of pct_pft_max_arr and pct_pft_arr have the same ! size and lower bound for their pct_p2l array. ! - ! !ARGUMENTS: + ! input/output variables ! workaround for gfortran bug (58043): declare this 'type' rather than 'class': type(pct_pft_type), intent(inout) :: pct_pft_max_arr(:) type(pct_pft_type), intent(in) :: pct_pft_arr(:) ! - ! !LOCAL VARIABLES: + ! local variables: integer :: pft_lbound integer :: pft_ubound integer :: arr_index integer :: pft_index - character(len=*), parameter :: subname = 'update_max_array' !----------------------------------------------------------------------- - - + + pft_lbound = lbound(pct_pft_arr(1)%pct_p2l, 1) pft_ubound = ubound(pct_pft_arr(1)%pct_p2l, 1) do arr_index = 1, size(pct_pft_arr) if (lbound(pct_pft_arr(arr_index)%pct_p2l, 1) /= pft_lbound .or. & - ubound(pct_pft_arr(arr_index)%pct_p2l, 1) /= pft_ubound) then + ubound(pct_pft_arr(arr_index)%pct_p2l, 1) /= pft_ubound) then write(6,*) subname//' ERROR: all elements of pct_pft_arr must have' write(6,*) 'the same size and lower bound for their pct_p2l array' - call abort() + call shr_sys_abort() end if - + if (pct_pft_arr(arr_index)%pct_l2g > pct_pft_max_arr(arr_index)%pct_l2g) then pct_pft_max_arr(arr_index)%pct_l2g = pct_pft_arr(arr_index)%pct_l2g end if @@ -559,68 +511,73 @@ subroutine update_max_array(pct_pft_max_arr,pct_pft_arr) end subroutine update_max_array !----------------------------------------------------------------------- - function get_pct_p2l_array(pct_pft_arr) result(pct_p2l) + subroutine get_pct_p2l_array(pct_pft_arr, ndim1, ndim2, pct_p2l) ! - ! !DESCRIPTION: ! Given an array of pct_pft_type variables, return a 2-d array of pct_p2l. ! ! Assumes that all elements of pct_pft_arr have the same size and lower bound for ! their pct_p2l array. ! - ! !ARGUMENTS: - real(r8), allocatable :: pct_p2l(:,:) ! function result (n_elements, n_pfts) + ! input/output variables ! workaround for gfortran bug (58043): declare this 'type' rather than 'class': - type(pct_pft_type), intent(in) :: pct_pft_arr(:) + type(pct_pft_type) , intent(in) :: pct_pft_arr(:) + integer , intent(in) :: ndim1 + integer , intent(in) :: ndim2 + real(r8) , intent(inout) :: pct_p2l(ndim1,ndim2) ! result (n_elements, n_pfts) ! - ! !LOCAL VARIABLES: + ! local variables: integer :: pft_lbound integer :: pft_ubound integer :: arr_index integer :: pft_index - character(len=*), parameter :: subname = 'get_pct_p2l_array' !----------------------------------------------------------------------- - + pft_lbound = lbound(pct_pft_arr(1)%pct_p2l, 1) pft_ubound = ubound(pct_pft_arr(1)%pct_p2l, 1) - allocate(pct_p2l(size(pct_pft_arr), pft_lbound:pft_ubound)) - + ! error checks + if (ndim1 /= size(pct_pft_arr)) then + write(6,*) 'ndim1, size(pct_pft_arr) = ',ndim1,size(pct_pft_arr) + call shr_sys_abort(subname//' ndim1 and size(pct_pft_arr) must be equal') + end if + if (ndim2 /= pft_ubound-pft_lbound+1) then + write(6,*) 'ndim2,pft_ubound-pft_lbound+1 = ',ndim2,pft_ubound-pft_lbound+1 + call shr_sys_abort(subname//' ndim2 and pft_ubound-pft_lbound+1 must be equal') + end if do arr_index = 1, size(pct_pft_arr) if (lbound(pct_pft_arr(arr_index)%pct_p2l, 1) /= pft_lbound .or. & - ubound(pct_pft_arr(arr_index)%pct_p2l, 1) /= pft_ubound) then + ubound(pct_pft_arr(arr_index)%pct_p2l, 1) /= pft_ubound) then write(6,*) subname//' ERROR: all elements of pct_pft_arr must have' write(6,*) 'the same size and lower bound for their pct_p2l array' - call abort() + call shr_sys_abort() end if - + end do + + do arr_index = 1, size(pct_pft_arr) do pft_index = pft_lbound, pft_ubound - pct_p2l(arr_index, pft_index) = pct_pft_arr(arr_index)%pct_p2l(pft_index) + pct_p2l(arr_index, pft_index - pft_lbound + 1) = pct_pft_arr(arr_index)%pct_p2l(pft_index) end do end do - end function get_pct_p2l_array + end subroutine get_pct_p2l_array !----------------------------------------------------------------------- - function get_pct_l2g_array(pct_pft_arr) result(pct_l2g) + subroutine get_pct_l2g_array(pct_pft_arr, pct_l2g) ! - ! !DESCRIPTION: ! Given an array of pct_pft_type variables, return an array of pct_l2g. ! - ! !ARGUMENTS: - real(r8), allocatable :: pct_l2g(:) ! function result - class(pct_pft_type), intent(in) :: pct_pft_arr(:) + ! input/output variables + class(pct_pft_type) , intent(in) :: pct_pft_arr(:) + real(r8) , intent(inout) :: pct_l2g(:) ! result ! - ! !LOCAL VARIABLES: + ! local variables: integer :: arr_index - character(len=*), parameter :: subname = 'get_pct_l2g_array' !----------------------------------------------------------------------- - - allocate(pct_l2g(size(pct_pft_arr))) - pct_l2g = pct_pft_arr(:)%pct_l2g - end function get_pct_l2g_array + pct_l2g = pct_pft_arr(:)%pct_l2g + end subroutine get_pct_l2g_array end module mkpctPftTypeMod diff --git a/tools/mksurfdata_esmf/src/mkpeatMod.F90 b/tools/mksurfdata_esmf/src/mkpeatMod.F90 new file mode 100644 index 0000000000..3acd93b755 --- /dev/null +++ b/tools/mksurfdata_esmf/src/mkpeatMod.F90 @@ -0,0 +1,150 @@ +module mkpeatMod + + !----------------------------------------------------------------------- + ! make fraction peat from input peat data + !----------------------------------------------------------------------- + + use ESMF + use shr_kind_mod , only : r8 => shr_kind_r8, r4=>shr_kind_r4 + use shr_sys_mod , only : shr_sys_abort + use pio , only : file_desc_t, pio_openfile, pio_closefile, pio_nowrite, pio_syncfile + use mkpioMod , only : mkpio_get_rawdata, pio_iotype, pio_iosystem + use mkesmfMod , only : regrid_rawdata, create_routehandle_r8 + use mkvarctl , only : ndiag, root_task, mpicom, spval + use mkchecksMod , only : min_bad, max_bad + use mkdiagnosticsMod , only : output_diagnostics_area + use mkutilsMod , only : chkerr + use mkfileMod , only : mkfile_output + + implicit none + private + + public :: mkpeat + + character(len=*) , parameter :: u_FILE_u = & + __FILE__ + +!=============================================================== +contains +!=============================================================== + + subroutine mkpeat(file_mesh_i, file_data_i, mesh_o, pioid_o, rc) + + ! input/output variables + character(len=*) , intent(in) :: file_mesh_i ! input mesh file name + character(len=*) , intent(in) :: file_data_i ! input data file name + type(ESMF_Mesh) , intent(in) :: mesh_o ! input model mesh + type(file_desc_t) , intent(inout) :: pioid_o + integer , intent(out) :: rc + + ! local variables: + type(ESMF_RouteHandle) :: routehandle + type(ESMF_Mesh) :: mesh_i + type(file_desc_t) :: pioid_i + integer :: ni,no,k + integer :: ns_i, ns_o + integer , allocatable :: mask_i(:) + real(r8), allocatable :: frac_i(:) + real(r8), allocatable :: frac_o(:) + real(r8), allocatable :: peat_i(:) ! input grid: percent peat + real(r8), allocatable :: peat_o(:) ! output grid: fraction peat + integer :: ier, rcode ! error status + real(r8), parameter :: min_valid = 0._r8 ! minimum valid value + real(r8), parameter :: max_valid = 100.000001_r8 ! maximum valid value + character(len=*), parameter :: subname = 'mkpeat' + !----------------------------------------------------------------------- + + if (root_task) then + write(ndiag,*) + write(ndiag,'(1x,80a1)') ('=',k=1,80) + write(ndiag,*) + write(ndiag,'(a)') 'Attempting to make peat .....' + write(ndiag,'(a)') ' Input file is '//trim(file_data_i) + write(ndiag,'(a)') ' Input mesh file is '//trim(file_mesh_i) + end if + call ESMF_VMLogMemInfo("At start of "//trim(subname)) + + ! Open input data file + rcode = pio_openfile(pio_iosystem, pioid_i, pio_iotype, trim(file_data_i), pio_nowrite) + + ! Read in input mesh + mesh_i = ESMF_MeshCreate(filename=trim(file_mesh_i), fileformat=ESMF_FILEFORMAT_ESMFMESH, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After create mesh_i in "//trim(subname)) + + ! Determine ns_i + call ESMF_MeshGet(mesh_i, numOwnedElements=ns_i, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Determine ns_o and allocate output data + call ESMF_MeshGet(mesh_o, numOwnedElements=ns_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + allocate (peat_o(ns_o)) ; peat_o(:) = spval + + ! Get the landmask from the file and reset the mesh mask based on that + allocate(frac_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort() + allocate(mask_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort() + call mkpio_get_rawdata(pioid_i, 'LANDMASK', mesh_i, frac_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + do ni = 1,ns_i + if (frac_i(ni) > 0._r8) then + mask_i(ni) = 1 + else + mask_i(ni) = 0 + end if + end do + call ESMF_MeshSet(mesh_i, elementMask=mask_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! Read in peat_i + allocate(peat_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort() + call mkpio_get_rawdata(pioid_i, 'peatf', mesh_i, peat_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After mkpio_getrawdata in "//trim(subname)) + + ! Create a route handle between the input and output mesh and get frac_o + allocate(frac_o(ns_o),stat=ier) + if (ier/=0) call shr_sys_abort() + call create_routehandle_r8(mesh_i=mesh_i, mesh_o=mesh_o, norm_by_fracs=.true., & + routehandle=routehandle, frac_o=frac_o, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After create routehandle in "//trim(subname)) + + ! Regrid peat + call regrid_rawdata(mesh_i, mesh_o, routehandle, peat_i, peat_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + if (min_bad(peat_o, min_valid, 'peat') .or. max_bad(peat_o, max_valid, 'peat')) then + call shr_sys_abort(subname//" peat_o does not fall in range of min_valid/max_valid") + end if + + ! Write out data to output file + if (root_task) write(ndiag, '(a)') trim(subname)//" writing out peatland fraction" + call mkfile_output(pioid_o, mesh_o, 'peatf', peat_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkfile_output') + call pio_syncfile(pioid_o) + + ! Output diagnostic info + call output_diagnostics_area(mesh_i, mesh_o, mask_i, frac_o, & + peat_i, peat_o, "Peat", percent=.false., ndiag=ndiag, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + + ! Close the file + call pio_closefile(pioid_i) + + ! Release memory + call ESMF_RouteHandleDestroy(routehandle, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + call ESMF_MeshDestroy(mesh_i, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + + if (root_task) then + write (ndiag,'(a)') 'Successfully made peat' + end if + call ESMF_VMLogMemInfo("At end of "//trim(subname)) + + end subroutine mkpeat + +end module mkpeatMod diff --git a/tools/mksurfdata_map/src/mkpftConstantsMod.F90 b/tools/mksurfdata_esmf/src/mkpftConstantsMod.F90 similarity index 89% rename from tools/mksurfdata_map/src/mkpftConstantsMod.F90 rename to tools/mksurfdata_esmf/src/mkpftConstantsMod.F90 index 241873c339..85152ef3c4 100644 --- a/tools/mksurfdata_map/src/mkpftConstantsMod.F90 +++ b/tools/mksurfdata_esmf/src/mkpftConstantsMod.F90 @@ -1,26 +1,15 @@ module mkpftConstantsMod + !----------------------------------------------------------------------- - !BOP - ! - ! !MODULE: mkpftConstants - ! - ! !DESCRIPTION: ! Constants used by mkpft and related code - ! - ! !REVISION HISTORY: - ! Author: Bill Sacks - ! !----------------------------------------------------------------------- - !!USES: + use shr_kind_mod, only : r8 => shr_kind_r8 implicit none private - ! - ! !PUBLIC DATA MEMBERS: - ! - + ! public data members: integer, parameter, public :: maxpft = 78 ! maximum # of PFT integer, public :: num_natpft = -1 ! number of PFTs on the natural vegetation diff --git a/tools/mksurfdata_esmf/src/mkpftMod.F90 b/tools/mksurfdata_esmf/src/mkpftMod.F90 new file mode 100644 index 0000000000..54827e7ad3 --- /dev/null +++ b/tools/mksurfdata_esmf/src/mkpftMod.F90 @@ -0,0 +1,587 @@ +module mkpftMod + + use ESMF + use pio + use shr_kind_mod , only : r8 => shr_kind_r8, r4=>shr_kind_r4 + use shr_sys_mod , only : shr_sys_abort + use mkpioMod , only : mkpio_get_rawdata, mkpio_get_dimlengths + use mkpioMod , only : pio_iotype, pio_ioformat, pio_iosystem + use mkpioMod , only : mkpio_iodesc_rawdata, mkpio_get_rawdata_level + use mkesmfMod , only : regrid_rawdata, create_routehandle_r8, get_meshareas + use mkutilsMod , only : chkerr + use mkvarctl , only : numpft, root_task, ndiag, mpicom + use mkvarpar , only : numstdpft, numstdcft, noveg + use mkpftConstantsMod + + implicit none + private ! By default make data private + +#include + + public :: mkpftInit ! Initialization + public :: mkpft ! Set PFT + + integer :: m ! index + + character(len=35) :: veg(0:maxpft) ! vegetation types + real(r8), allocatable :: frac_o_nonorm(:) + type(ESMF_RouteHandle) :: routehandle_nonorm + + character(len=*) , parameter :: u_FILE_u = & + __FILE__ + +!=============================================================== +contains +!=============================================================== + + subroutine mkpftInit( ) + ! + ! Initialize of PFT data + ! + ! local variables: + character(len=*), parameter :: subname = ' (mkpftInit) ' + !----------------------------------------------------------------------- + + if ( maxpft < numpft ) then + write(6,*) subname//'number PFT is > max allowed!' + call shr_sys_abort() + end if + + ! Determine number of PFTs on the natural vegetation landunit, and number of CFTs on + ! the crop landunit. + ! + ! For the sake of dynamic PFTs and dynamic landunits, it helps for the structure of the + ! surface dataset to reflect the subgrid structure that will be used by CLM. Currently + ! generic crops will always go on the crop landunit, regardless of whether or not we're + ! using the extra specific crops (so we always run CLM with create_crop_landunit=.true.). + ! When we create a surface dataset WITH the extra specific crops, all crops + ! (including the generic crops) again go on the crop landunit. + num_natpft = numstdpft - numstdcft + num_cft = numpft - num_natpft + + ! Determine array bounds for arrays of just natural pfts and just crops. Note that + ! these are set up so that they always span 0:numpft, so that there is a 1:1 + ! correspondence between an element in a full 0:numpft array and an element with the + ! same index in either a natpft array or a cft array. + natpft_lb = noveg + natpft_ub = num_natpft + cft_lb = num_natpft+1 + cft_ub = cft_lb + num_cft - 1 + + if (root_task) then + write(ndiag, '(a, i8)') subname//' num_natpft = ',num_natpft + write(ndiag, '(a, i8)') subname//' natpft_lb = ',natpft_lb + write(ndiag, '(a, i8)') subname//' natpft_ub = ',natpft_ub + write(ndiag, '(a, i8)') subname//' num_cft = ',num_cft + write(ndiag, '(a, i8)') subname//' cft_lb = ',cft_lb + write(ndiag, '(a, i8)') subname//' cft_ub = ',cft_ub + end if + + ! Make sure the array indices have been set up properly, to ensure the 1:1 + ! correspondence mentioned above + if (cft_ub /= numpft) then + write(6,*) 'CFT_UB set up incorrectly: cft_ub, numpft = ', cft_ub, numpft + call shr_sys_abort() + end if + + ! ----------------------------------------------------------------- + ! Set the vegetation types + ! ----------------------------------------------------------------- + + if ( numpft >= numstdpft ) then + veg(0:maxpft) = (/ & + 'not vegetated ', & + 'needleleaf evergreen temperate tree', & + 'needleleaf evergreen boreal tree ', & + 'needleleaf deciduous boreal tree ', & + 'broadleaf evergreen tropical tree ', & + 'broadleaf evergreen temperate tree ', & + 'broadleaf deciduous tropical tree ', & + 'broadleaf deciduous temperate tree ', & + 'broadleaf deciduous boreal tree ', & + 'broadleaf evergreen shrub ', & + 'broadleaf deciduous temperate shrub', & + 'broadleaf deciduous boreal shrub ', & + 'c3 arctic grass ', & + 'c3 non-arctic grass ', & + 'c4 grass ', & + 'c3_crop ', & + 'c3_irrigated ', & + 'temperate_corn ', & + 'irrigated_temperate_corn ', & + 'spring_wheat ', & + 'irrigated_spring_wheat ', & + 'winter_wheat ', & + 'irrigated_winter_wheat ', & + 'temperate_soybean ', & + 'irrigated_temperate_soybean ', & + 'barley ', & + 'irrigated_barley ', & + 'winter_barley ', & + 'irrigated_winter_barley ', & + 'rye ', & + 'irrigated_rye ', & + 'winter_rye ', & + 'irrigated_winter_rye ', & + 'cassava ', & + 'irrigated_cassava ', & + 'citrus ', & + 'irrigated citrus ', & + 'cocoa ', & + 'irrigated_cocoa ', & + 'coffee ', & + 'irrigated_coffee ', & + 'cotton ', & + 'irrigated_cotton ', & + 'datepalm ', & + 'irrigated_datepalm ', & + 'foddergrass ', & + 'irrigated_foddergrass ', & + 'grapes ', & + 'irrigated_grapes ', & + 'groundnuts ', & + 'irrigated_groundnuts ', & + 'millet ', & + 'irrigated_millet ', & + 'oilpalm ', & + 'irrigated_oilpalm ', & + 'potatoes ', & + 'irrigated_potatoes ', & + 'pulses ', & + 'irrigated_pulses ', & + 'rapeseed ', & + 'irrigated_rapeseed ', & + 'rice ', & + 'irrigated_rice ', & + 'sorghum ', & + 'irrigated_sorghum ', & + 'sugarbeet ', & + 'irrigated_sugarbeet ', & + 'sugarcane ', & + 'irrigated_sugarcane ', & + 'sunflower ', & + 'irrigated_sunflower ', & + 'miscanthus ', & + 'irrigated_miscanthus ', & + 'switchgrass ', & + 'irrigated_switchgrass ', & + 'tropical_corn ', & + 'irrigated_tropical_corn ', & + 'tropical_soybean ', & + 'irrigated_tropical_soybean ' /) + end if + if (numpft == numstdpft )then + if (root_task) then + write(ndiag, '(a,i8)')'Creating surface datasets with the standard # of PFTs =', numpft + end if + else if ( numpft > numstdpft )then + if (root_task) then + write(ndiag,'(a,i8)')'Creating surface datasets with extra types for crops; total pfts =', numpft + end if + else + write(6,*) subname//': parameter numpft is NOT set to a known value (should be 16 or more) =',numpft + call shr_sys_abort() + end if + + end subroutine mkpftInit + + !=============================================================== + subroutine mkpft(file_mesh_i, file_data_i, mesh_o, pctlnd_o, pctnatpft_o, & + pctcft_o, rc) + ! + ! Make PFT data + ! + ! This dataset consists of the %cover of the [numpft]+1 PFTs used by + ! the model. The input %cover pertains to the "vegetated" portion of the + ! grid cell and sums to 100. The real portion of each grid cell + ! covered by each PFT is the PFT cover times the fraction of the + ! grid cell that is land. This is the quantity preserved when + ! area-averaging from the input grid to the models grid. + ! + ! Upon return from this routine, the % cover of the natural veg + crop landunits is + ! generally 100% everywhere; this will be normalized later to account for special landunits. + ! + use mkpctPftTypeMod, only : pct_pft_type + use mkpftConstantsMod, only : natpft_lb, natpft_ub, num_cft, cft_lb, cft_ub + use mkinputMod, only : mksrf_fdynuse + ! + ! input/output variables + character(len=*) , intent(in) :: file_mesh_i ! input mesh file name + character(len=*) , intent(in) :: file_data_i ! input data file name + type(ESMF_Mesh) , intent(in) :: mesh_o ! model mesh + real(r8) , intent(out) :: pctlnd_o(:) ! output grid:%land/gridcell + type(pct_pft_type), intent(inout) :: pctnatpft_o(:) ! natural PFT cover + type(pct_pft_type), intent(inout) :: pctcft_o(:) ! crop (CFT) cover + + integer , intent(out) :: rc + ! + ! local variables: + type(ESMF_Mesh) :: mesh_i + type(file_desc_t) :: pioid + integer :: dimid + integer :: ndims ! number of dimensions for a variable on the file + integer, allocatable :: dimlens(:) ! dimension lengths for a variable on the file + integer :: ns_i, ns_o ! input/output bounds + integer :: ni,no ! indices + integer :: k,n,m ! indices + type(pct_pft_type), allocatable :: pctnatpft_i(:) ! input natural PFT cover + type(pct_pft_type), allocatable :: pctcft_i(:) ! input crop (CFT) cover + real(r8), allocatable :: pct_cft_i(:,:) ! input CFT (Crop Functional Type) percent (% of landunit cell) + real(r8), allocatable :: pct_cft_o(:,:) ! output CFT (Crop Functional Type) percent (% of landunit cell) + real(r8), allocatable :: pct_nat_pft_i(:,:) ! input natural PFT percent (% of landunit cell) + real(r8), allocatable :: pct_nat_pft_o(:,:) ! output natural PFT percent (% of landunit cell) + real(r8), allocatable :: output_pct_nat_pft_o(:,:) + real(r8), allocatable :: output_pct_cft_o(:,:) + integer , allocatable :: mask_i(:) + real(r8), allocatable :: frac_i(:) + real(r8), allocatable :: pctlnd_i(:) ! input land fraction + real(r8), allocatable :: pctnatveg_i(:) ! input natural veg percent (% of grid cell) + real(r8), allocatable :: pctnatveg_o(:) ! output natural veg percent (% of grid cell) + real(r8), allocatable :: pctcrop_i(:) ! input all crop percent (% of grid cell) + real(r8), allocatable :: pctcrop_o(:) ! output all crop percent (% of grid cell) + real(r8), allocatable :: pctpft_i(:,:) ! input PFT percent (for error checks) + real(r8), allocatable :: pctpft_o(:,:) ! output PFT percent (% of grid cell) + real(r8), allocatable :: temp_i(:,:) ! input temporary 2D variable to read in + integer :: numpft_i ! num of plant types input data + integer :: natpft_i ! num of natural plant types input data + integer :: ncft_i ! num of crop types input data + real(r8) :: wst_sum ! sum of %pft + real(r8), allocatable :: area_o(:) + real(r8), allocatable :: loc_gpft_o(:) ! output global area pfts + real(r8), allocatable :: glob_gpft_o(:) ! output global area pfts + integer :: ier, rcode ! error status + real(r8) :: relerr = 0.0001_r8 ! max error: sum overlap wts ne 1 + character(len=*), parameter :: subname = 'mkpft' + !----------------------------------------------------------------------- + + if (root_task) then + write(ndiag,*) + write(ndiag,'(1x,80a1)') ('=',k=1,80) + write(ndiag,*) + write(ndiag,'(a)') 'Attempting to make PFTs .....' + write(ndiag,'(a)') ' Input file is '//trim(file_data_i) + write(ndiag,'(a)') ' Input mesh file is '//trim(file_mesh_i) + end if + + ! Open input pft file + rcode = pio_openfile(pio_iosystem, pioid, pio_iotype, trim(file_data_i), pio_nowrite) + call ESMF_VMLogMemInfo("After pio_openfile "//trim(file_data_i)) + + ! Read in input mesh + mesh_i = ESMF_MeshCreate(filename=trim(file_mesh_i), fileformat=ESMF_FILEFORMAT_ESMFMESH, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After create mesh_i in "//trim(subname)) + + ! Determine ns_i + call ESMF_MeshGet(mesh_i, numOwnedElements=ns_i, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Determine ns_o + call ESMF_MeshGet(mesh_o, numOwnedElements=ns_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Get the landmask from the file and reset the mesh mask based on that + allocate(frac_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort() + allocate(mask_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort() + call mkpio_get_rawdata(pioid, 'LANDMASK', mesh_i, frac_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + do ni = 1,ns_i + if (frac_i(ni) > 0._r4) then + mask_i(ni) = 1 + else + mask_i(ni) = 0 + end if + end do + call ESMF_MeshSet(mesh_i, elementMask=mask_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! Create error checks + rcode = pio_inq_dimid(pioid, 'natpft', dimid) + rcode = pio_inq_dimlen(pioid, dimid, natpft_i) + rcode = pio_inq_dimid(pioid, 'cft', dimid) + rcode = pio_inq_dimlen(pioid, dimid, ncft_i) + numpft_i = natpft_i + ncft_i + + ! Check if the number of pfts on the input matches the expected number. A mismatch + ! is okay if the input raw dataset has prognostic crops and the output does not. + if (numpft_i /= numpft+1) then + if (numpft_i == numstdpft+1) then + if (root_task) then + write(ndiag,*) subname//' ERROR: trying to use non-crop input file' + write(ndiag,*) 'for a surface dataset with crops.' + end if + call shr_sys_abort() + else if (numpft_i > numstdpft+1 .and. numpft_i == maxpft+1) then + if (root_task) then + write(ndiag,*) subname//' WARNING: using a crop input raw dataset for a non-crop output surface dataset' + end if + else + if (root_task) then + write(ndiag,*) subname//': parameter numpft+1= ',numpft+1, & + 'does not equal input dataset numpft= ',numpft_i + end if + call shr_sys_abort() + end if + endif + + ! ---------------------------------------- + ! Create a route handle between the input and output mesh and get frac_o_nonorm + ! ---------------------------------------- + if (.not. ESMF_RouteHandleIsCreated(routehandle_nonorm)) then + allocate(frac_o_nonorm(ns_o),stat=ier) + if (ier/=0) call shr_sys_abort() + ! Note that norm_by_fracs is false in the following because this routehandle is + ! used to map fields that are expressed in terms of % of the grid cell. + call create_routehandle_r8(mesh_i=mesh_i, mesh_o=mesh_o, norm_by_fracs=.false., & + routehandle=routehandle_nonorm, frac_o=frac_o_nonorm, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After create routehandle in "//trim(subname)) + end if + + ! ---------------------------------------- + ! Determine pctlnd_o(:) + ! ---------------------------------------- + allocate(pctlnd_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort('error allocating pctlnd_i') + + call mkpio_get_rawdata(pioid, 'LANDFRAC', mesh_i, pctlnd_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + call regrid_rawdata(mesh_i, mesh_o, routehandle_nonorm, pctlnd_i, pctlnd_o, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + ! Convert from fraction to percent: + pctlnd_o(:) = pctlnd_o(:) * 100._r8 + + ! ---------------------------------------- + ! Determine pct_nat_pft_o(:,:) + ! ---------------------------------------- + allocate(pctnatveg_o(ns_o), stat=ier) + if (ier/=0) call shr_sys_abort('error in allocating pctnatveg_o') + + ! First determine pctnatveg_o(:) + ! Read in pctnatveg_i + allocate(pctnatveg_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort('error allocating pctnatveg_i') + + call mkpio_get_rawdata(pioid, 'PCT_NATVEG', mesh_i, pctnatveg_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! Regrid to determine pctnatveg_o + call regrid_rawdata(mesh_i, mesh_o, routehandle_nonorm, pctnatveg_i, pctnatveg_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + allocate(pct_nat_pft_i(0:num_natpft,ns_i)) + if (ier/=0) call shr_sys_abort() + allocate(pct_nat_pft_o(0:num_natpft,ns_o)) + if (ier/=0) call shr_sys_abort() + + ! Read in pct_nat_pft_i + call mkpio_get_rawdata(pioid, 'PCT_NAT_PFT', mesh_i, pct_nat_pft_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + do ni = 1,ns_i + do m = 0,num_natpft + pct_nat_pft_i(m,ni) = pct_nat_pft_i(m,ni) * (pctnatveg_i(ni) * 0.01_r8 * mask_i(ni)) + end do + end do + + ! Readgrid to determine pct_nat_pft_o + call regrid_rawdata(mesh_i, mesh_o, routehandle_nonorm, pct_nat_pft_i, pct_nat_pft_o, 0, num_natpft, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Rescale pct_nat_pft_o, and set tiny pctnatveg to 0 + do no = 1,ns_o + if (pctnatveg_o(no) >= 1.0e-6_r8) then + do m = 0,num_natpft + pct_nat_pft_o(m,no) = pct_nat_pft_o(m,no) / (pctnatveg_o(no) * 0.01_r8) + end do + else + pctnatveg_o(no) = 0._r8 + pct_nat_pft_o(0,no) = 100._r8 + pct_nat_pft_o(1:num_natpft,no) = 0._r8 + end if + + ! Correct sums so that if they differ slightly from 100, they are + ! corrected to equal 100 more exactly. + ! Error check: percents should sum to 100 for land grid cells, within roundoff + wst_sum = 0. + do m = 0, num_natpft + wst_sum = wst_sum + pct_nat_pft_o(m,no) + enddo + if (abs(wst_sum - 100._r8) > relerr) then + write (6,*) subname//'error: nat pft = ', (pct_nat_pft_o(m,no), m = 0, num_natpft), & + ' do not sum to 100. at no = ',no,' but to ', wst_sum + call shr_sys_abort() + end if + do m = 1, num_natpft + pct_nat_pft_o(m,no) = pct_nat_pft_o(m,no) * 100._r8 / wst_sum + end do + end do + + ! ---------------------------------------- + ! Determine pct_cft_o(:,:) + ! ---------------------------------------- + + ! First Determine pctcrop_o(:) + allocate(pctcrop_o(ns_o), stat=ier) + if (ier/=0) call shr_sys_abort('error allocating pctcrop_o_o') + allocate(pctcrop_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort() + call mkpio_get_rawdata(pioid, 'PCT_CROP', mesh_i, pctcrop_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call regrid_rawdata(mesh_i, mesh_o, routehandle_nonorm, pctcrop_i, pctcrop_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + allocate(pct_cft_i(1:num_cft,ns_i), stat=ier) + if (ier/=0) call shr_sys_abort() + allocate(pct_cft_o(1:num_cft,ns_o), stat=ier) + if (ier/=0) call shr_sys_abort() + + ! Get dimensions for PCT_CFT + allocate(dimlens(3)) + call mkpio_get_dimlengths(pioid, 'PCT_CFT', ndims, dimlens(:)) + if (root_task) then + do n = 1,ndims + write(ndiag,'(a,i8,i8)')' dimid, length= ',n,dimlens(n) + end do + write(ndiag,'(a,i8)')' num_cft = ',num_cft + end if + + ! Read in pct_cft_i + if (dimlens(ndims) == num_cft )then + call mkpio_get_rawdata(pioid, 'PCT_CFT', mesh_i, pct_cft_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + else if (dimlens(ndims) > num_cft )then + ! Read in the whole array: then sum the rainfed and irrigated seperately + allocate(temp_i(dimlens(3),ns_i)) + call mkpio_get_rawdata(pioid, 'PCT_CFT', mesh_i, temp_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + do n = 1, num_cft + pct_cft_i(n,:) = 0.0_r8 + do m = n, dimlens(3), 2 + pct_cft_i(n,:) = pct_cft_i(n,:) + temp_i(m,:) + end do + end do + deallocate(temp_i) + else + call shr_sys_abort(subname//' error: dimensions for PCT_CROP are NOT what is expected') + end if + do ni = 1,ns_i + do m = 1,num_cft + pct_cft_i(m,ni) = pct_cft_i(m,ni) * (pctcrop_i(ni) * 0.01_r8 * mask_i(ni)) + end do + end do + + ! Readgrid pct_cft_i to determine pct_cft_o + call regrid_rawdata(mesh_i, mesh_o, routehandle_nonorm, pct_cft_i, pct_cft_o, 1, num_cft, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Rescale pct_cft_o, and set tiny pctcrop to 0 + do no = 1,ns_o + if (pctcrop_o(no) >= 1.0e-6_r8) then + do m = 1,num_cft + pct_cft_o(m,no) = pct_cft_o(m,no) / (pctcrop_o(no) * 0.01_r8) + end do + else + pctcrop_o(no) = 0._r8 + pct_cft_o(1,no) = 100._r8 + pct_cft_o(2:num_cft,no) = 0._r8 + end if + + ! Correct sums so that if they differ slightly from 100, they are + ! corrected to equal 100 more exactly. + ! Error check: percents should sum to 100 for land grid cells, within roundoff + wst_sum = 0. + do m = 1, num_cft + wst_sum = wst_sum + pct_cft_o(m,no) + enddo + if (abs(wst_sum-100._r8) > relerr) then + write (6,*) subname//'error: crop cft = ',(pct_cft_o(no,m), m = 1, num_cft), & + ' do not sum to 100. at no = ',no,' but to ', wst_sum + call shr_sys_abort() + end if + do m = 1, num_cft + pct_cft_o(m,no) = pct_cft_o(m,no) * 100._r8 / wst_sum + end do + enddo + ! ---------------------------------------- + ! Convert % pft as % of grid cell to % pft on the landunit and % of landunit on the grid cell + ! *** NOTE*** pctnatpft_o and pctcft_o are output arguments + ! ---------------------------------------- + allocate(output_pct_nat_pft_o(ns_o, 0:num_natpft), stat=ier) + if (ier/=0) call shr_sys_abort('error in allocating output_pct_nat_pft_o') + allocate(output_pct_cft_o(ns_o, 1:num_cft), stat=ier) + if (ier/=0) call shr_sys_abort('error in allocating output_pct_cft_o') + + do no = 1,ns_o + output_pct_nat_pft_o(no,:) = pct_nat_pft_o(:,no) + pctnatpft_o(no) = pct_pft_type( output_pct_nat_pft_o(no,:), pctnatveg_o(no), first_pft_index=natpft_lb ) + + output_pct_cft_o(no,:) = pct_cft_o(:,no) + pctcft_o(no) = pct_pft_type( output_pct_cft_o(no,:), pctcrop_o(no), first_pft_index=cft_lb) + end do + + deallocate(output_pct_nat_pft_o) + deallocate(output_pct_cft_o) + + ! ----------------------------------------------------------------- + ! Error check + ! Output global sums on output grid + ! ----------------------------------------------------------------- + + allocate(area_o(ns_o)) + call get_meshareas(mesh_o, area_o, rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + allocate(pctpft_o(ns_o,0:(numpft_i-1)), stat=ier) + if (ier/=0) call shr_sys_abort() + do no = 1,ns_o + pctpft_o(no,natpft_lb:natpft_ub) = pctnatpft_o(no)%get_pct_p2g() + pctpft_o(no,cft_lb:cft_ub) = pctcft_o(no)%get_pct_p2g() + end do + + allocate(loc_gpft_o(0:numpft_i-1)) + allocate(glob_gpft_o(0:numpft_i-1)) + loc_gpft_o(:) = 0. + do no = 1,ns_o + do m = 0, numpft_i-1 + loc_gpft_o(m) = loc_gpft_o(m) + pctpft_o(no,m) * area_o(no) * frac_o_nonorm(no) + end do + end do + do m = 0,numpft_i-1 + call mpi_reduce(loc_gpft_o(m), glob_gpft_o(m), 1, MPI_REAL8, MPI_SUM, 0, mpicom, ier) + end do + + if (root_task) then + write (ndiag,*) + write (ndiag,'(1x,70a1)') ('.',k=1,70) + write (ndiag,*) 'PFTs Output' + write (ndiag,101) +101 format (1x,'plant type ',20x,' output grid area',/ & + 1x,33x,' 10**6 km**2') + write (ndiag,'(1x,70a1)') ('.',k=1,70) + write (ndiag,*) + do m = 0, numpft_i - 1 + write (ndiag,102) veg(m), glob_gpft_o(m)*1.e-06/100. + end do +102 format (1x,a35,f17.3) + end if + + ! Clean up memory + if (mksrf_fdynuse == ' ') then ! ...else we will reuse it + deallocate(frac_o_nonorm) + call ESMF_RouteHandleDestroy(routehandle_nonorm, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + end if + call ESMF_MeshDestroy(mesh_i, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + + if (root_task) then + write (ndiag,'(a)') 'Successfully made PFTs' + write (ndiag,*) + end if + + end subroutine mkpft + +end module mkpftMod diff --git a/tools/mksurfdata_map/src/mkpftUtilsMod.F90 b/tools/mksurfdata_esmf/src/mkpftUtilsMod.F90 similarity index 79% rename from tools/mksurfdata_map/src/mkpftUtilsMod.F90 rename to tools/mksurfdata_esmf/src/mkpftUtilsMod.F90 index 4a9ea12f97..7bfae0c0b1 100644 --- a/tools/mksurfdata_map/src/mkpftUtilsMod.F90 +++ b/tools/mksurfdata_esmf/src/mkpftUtilsMod.F90 @@ -1,34 +1,18 @@ module mkpftUtilsMod !----------------------------------------------------------------------- - !BOP - ! - ! !MODULE: mkpftUtils - ! - ! !DESCRIPTION: ! Lower-level utilities used in making PFT data. ! ! These are separated out from mkpftMod mainly as an aid to testing. - ! - ! !REVISION HISTORY: - ! Author: Bill Sacks - ! !----------------------------------------------------------------------- - !!USES: + use shr_kind_mod, only : r8 => shr_kind_r8 + use shr_sys_mod , only : shr_sys_abort implicit none private - ! - ! !PUBLIC MEMBER FUNCTIONS: - ! public :: convert_from_p2g ! Convert a p2g array into pct_pft_type objects - public :: adjust_total_veg_area ! Adjust the total vegetated area (natural veg & crop) to a new specified total - - ! - ! !PRIVATE MEMBER FUNCTIONS: - ! private :: get_default_natpft ! Get the default natural pft breakdown, for a 0-area natural veg. landunit private :: get_default_cft ! Get the default cft breakdown, for a 0-area crop landunit @@ -38,12 +22,10 @@ module mkpftUtilsMod module procedure convert_from_p2g_missing_crops end interface convert_from_p2g - !EOP - !=============================================================== +!=============================================================== contains - !=============================================================== +!=============================================================== - !----------------------------------------------------------------------- subroutine convert_from_p2g_default(pct_p2g, pctnatpft, pctcft) ! ! !DESCRIPTION: @@ -69,7 +51,7 @@ subroutine convert_from_p2g_default(pct_p2g, pctnatpft, pctcft) if (ubound(pct_p2g, 1) /= cft_ub) then write(6,*) subname, ' ERROR: upper bound of pct_p2g should be cft_ub' write(6,*) 'ubound(pct_p2g), cft_ub = ', ubound(pct_p2g), cft_ub - call abort() + call shr_sys_abort() end if allocate(default_natpft(natpft_lb:natpft_ub)) @@ -135,7 +117,7 @@ subroutine convert_from_p2g_missing_crops(pct_p2g, pctcft_saved, pctnatpft, pctc if (num_cft == 0) then write(6,*) subname, ' ERROR: this routine should only be called when running with prognostic crops' write(6,*) '(i.e., with num_cft > 0)' - call abort() + call shr_sys_abort() end if do pft_index = natpft_ub + 1, ubound(pct_p2g, 1) @@ -146,7 +128,7 @@ subroutine convert_from_p2g_missing_crops(pct_p2g, pctcft_saved, pctnatpft, pctc write(6,*) '(we do not currently handle the case where the transient input dataset' write(6,*) 'has non-zero areas for both pft 15 and pft 16)' write(6,*) 'pft_index, area = ', pft_index, pct_p2g(pft_index) - call abort() + call shr_sys_abort() end if end do @@ -214,44 +196,6 @@ function get_default_cft() result(default_cft) end function get_default_cft - !----------------------------------------------------------------------- - subroutine adjust_total_veg_area(new_total_pct, pctnatpft, pctcft) - ! - ! !DESCRIPTION: - ! Adjust the total vegetated area on the grid cell (natural veg & crop) to a new - ! specified total. - ! - ! If the old areas are 0%, then all the new area goes into pctnatpft. - ! - ! !USES: - use mkpctPftTypeMod, only : pct_pft_type - ! - ! !ARGUMENTS: - real(r8), intent(in) :: new_total_pct ! new total % of natural veg + crop landunits - class(pct_pft_type), intent(inout) :: pctnatpft ! natural veg cover information - class(pct_pft_type), intent(inout) :: pctcft ! crop cover information - ! - ! !LOCAL VARIABLES: - real(r8) :: natpft_l2g ! grid cell % cover of nat. veg. - real(r8) :: cft_l2g ! grid cell % cover of crop - real(r8) :: old_total ! old total % cover of natural veg + crop landunits - - character(len=*), parameter :: subname = 'adjust_total_veg_area' - !----------------------------------------------------------------------- - - natpft_l2g = pctnatpft%get_pct_l2g() - cft_l2g = pctcft%get_pct_l2g() - old_total = natpft_l2g + cft_l2g - if (old_total > 0._r8) then - call pctnatpft%set_pct_l2g(natpft_l2g * new_total_pct / old_total) - call pctcft%set_pct_l2g(cft_l2g * new_total_pct / old_total) - else - call pctnatpft%set_pct_l2g(new_total_pct) - end if - - end subroutine adjust_total_veg_area - - end module mkpftUtilsMod diff --git a/tools/mksurfdata_esmf/src/mkpioMod.F90 b/tools/mksurfdata_esmf/src/mkpioMod.F90 new file mode 100644 index 0000000000..589fb0b464 --- /dev/null +++ b/tools/mksurfdata_esmf/src/mkpioMod.F90 @@ -0,0 +1,1280 @@ +module mkpioMod + + use ESMF + use pio + use shr_kind_mod , only : r8 => shr_kind_r8, r4 => shr_kind_r4 + use shr_kind_mod , only : i2 => shr_kind_i2, i4 => shr_kind_i4 + use shr_kind_mod , only : cl => shr_kind_cl, cs => shr_kind_cs + use shr_sys_mod , only : shr_sys_abort + use mkutilsMod , only : chkerr + use mkvarctl , only : root_task, ndiag, mpicom, outnc_1d + + implicit none + private + +#include + + public :: mkpio_get_rawdata + public :: mkpio_get_rawdata_level + public :: mkpio_iodesc_rawdata + public :: mkpio_iodesc_output + public :: mkpio_wopen + public :: mkpio_close + public :: mkpio_defvar + public :: mkpio_def_spatial_var + public :: mkpio_get_dimlengths + public :: mkpio_put_time_slice + + interface mkpio_get_rawdata_level + module procedure mkpio_get_rawdata1d_level_real4 + module procedure mkpio_get_rawdata1d_level_real8 + module procedure mkpio_get_rawdata2d_level_real8 + end interface mkpio_get_rawdata_level + + interface mkpio_get_rawdata + module procedure mkpio_get_rawdata1d_int + module procedure mkpio_get_rawdata1d_real4 + module procedure mkpio_get_rawdata1d_real8 + module procedure mkpio_get_rawdata2d_real4 + module procedure mkpio_get_rawdata2d_real8 + end interface mkpio_get_rawdata + + interface mkpio_def_spatial_var + module procedure mkpio_def_spatial_var_0lev + module procedure mkpio_def_spatial_var_1lev + module procedure mkpio_def_spatial_var_2lev + end interface mkpio_def_spatial_var + + interface mkpio_put_time_slice + module procedure mkpio_put_time_slice_1d + module procedure mkpio_put_time_slice_2d + end interface mkpio_put_time_slice + + integer , public :: pio_iotype + integer , public :: pio_ioformat + type(iosystem_desc_t) , public :: pio_iosystem + + logical :: debug = .false. + + character(len=*) , parameter :: u_FILE_u = & + __FILE__ + +!=============================================================== +contains +!=============================================================== + + subroutine mkpio_get_rawdata1d_int(pioid, varname, mesh_i, data_i, rc) + + ! input/output variables + type(file_desc_t), intent(inout) :: pioid + character(len=*) , intent(in) :: varname ! field name in rawdata file + type(ESMF_Mesh) , intent(in) :: mesh_i + integer , intent(inout) :: data_i(:) ! input raw data + integer , intent(out) :: rc + + ! local variables + type(var_desc_t) :: pio_varid + integer :: pio_vartype + type(io_desc_t) :: pio_iodesc + type(io_desc_t) :: pio_iodesc_mask + integer :: lsize + integer :: rcode + integer :: n + integer(i2), allocatable :: data_short(:) + character(len=*), parameter :: subname = 'mkpio_get_rawdata1d_int' + !------------------------------------------------- + + rc = ESMF_SUCCESS + + ! Get data_i - Read in varname from filename + lsize = size(data_i) + + ! Create io descriptor for input raw data + ! This will query the raw data file for the dimensions of the variable varname and + ! create iodesc for either single or multi level input data + call mkpio_iodesc_rawdata(mesh_i, trim(varname), pioid, pio_varid, pio_vartype, pio_iodesc, rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After mkpio_iodesc for "//trim(varname)//" in "//trim(subname)) + + ! Read the input raw data + if (pio_vartype == PIO_INT) then + call pio_read_darray(pioid, pio_varid, pio_iodesc, data_i, rcode) + else if (pio_vartype == PIO_SHORT) then + allocate(data_short(lsize)) + call pio_read_darray(pioid, pio_varid, pio_iodesc, data_short, rcode) + data_i = int(data_short, i4) + deallocate(data_short) + else + call shr_sys_abort(subName//" ERROR: only int and short is supported for "//trim(varname)) + end if + call ESMF_VMLogMemInfo("After pio_read_darray for "//trim(varname)//" in "//trim(subname)) + + ! Free the memory of the io descriptor + call pio_freedecomp(pioid, pio_iodesc) + call ESMF_VMLogMemInfo("After call to pio_freedecomp for "//trim(varname)) + + end subroutine mkpio_get_rawdata1d_int + + !=============================================================== + subroutine mkpio_get_rawdata1d_real4(pioid, varname, mesh_i, data_i, rc) + + ! input/output variables + type(file_desc_t), intent(inout) :: pioid + character(len=*) , intent(in) :: varname ! field name in rawdata file + type(ESMF_Mesh) , intent(in) :: mesh_i + real(r4) , intent(inout) :: data_i(:) ! input raw data + integer , intent(out) :: rc + + ! local variables + type(var_desc_t) :: pio_varid + integer :: pio_vartype + type(io_desc_t) :: pio_iodesc + type(io_desc_t) :: pio_iodesc_mask + integer(i2) , allocatable :: data_short(:) + integer(i4) , allocatable :: data_int(:) + real(r8) , allocatable :: data_double(:) + integer :: lsize + integer :: rcode + integer :: n + character(len=*), parameter :: subname = 'mkpio_get_rawdata1d_real4' + !------------------------------------------------- + + rc = ESMF_SUCCESS + + ! Get data_i - Read in varname from filename + lsize = size(data_i) + + ! Create io descriptor for input raw data + ! This will query the raw data file for the dimensions of the variable varname and + ! create iodesc for either single or multi level input data + call mkpio_iodesc_rawdata(mesh_i, trim(varname), pioid, pio_varid, pio_vartype, pio_iodesc, rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After mkpio_iodesc for varname "//trim(varname)//" in "//trim(subname)) + + ! Read the input raw data + if (pio_vartype == PIO_SHORT) then + allocate(data_short(lsize)) + call pio_read_darray(pioid, pio_varid, pio_iodesc, data_short, rcode) + data_i(:) = real(data_short(:), kind=r8) + deallocate(data_short) + else if (pio_vartype == PIO_INT) then + allocate(data_int(lsize)) + call pio_read_darray(pioid, pio_varid, pio_iodesc, data_int, rcode) + data_i(:) = real(data_int(:), kind=r4) + deallocate(data_int) + else if (pio_vartype == PIO_REAL) then + call pio_read_darray(pioid, pio_varid, pio_iodesc, data_i, rcode) + else if (pio_vartype == PIO_DOUBLE) then + allocate(data_double(lsize)) + call pio_read_darray(pioid, pio_varid, pio_iodesc, data_double, rcode) + data_i(:) = real(data_double(:), kind=r4) + deallocate(data_double) + else + call shr_sys_abort(subName//" ERROR: only real and double types are supported for "//trim(varname)) + end if + call ESMF_VMLogMemInfo("After call to pio_read_darray for varname "//trim(varname)) + + call pio_freedecomp(pioid, pio_iodesc) + call ESMF_VMLogMemInfo("After call to pio_freedecomp for "//trim(varname)) + + end subroutine mkpio_get_rawdata1d_real4 + + !=============================================================== + subroutine mkpio_get_rawdata1d_real8(pioid, varname, mesh_i, data_i, nt, rc) + + ! input/output variables + type(file_desc_t), intent(inout) :: pioid + character(len=*) , intent(in) :: varname ! field name in rawdata file + type(ESMF_Mesh) , intent(in) :: mesh_i + real(r8) , intent(inout) :: data_i(:) ! input raw data + integer, optional, intent(in) :: nt + integer , intent(out) :: rc + + + ! local variables + type(var_desc_t) :: pio_varid + integer :: pio_vartype + type(io_desc_t) :: pio_iodesc + type(io_desc_t) :: pio_iodesc_mask + integer(i2) , allocatable :: data_short(:) + integer(i4) , allocatable :: data_int(:) + real(r4) , allocatable :: data_real(:) + real(r8) , allocatable :: data_double(:) + integer :: lsize + integer :: rcode + integer :: n + character(len=*), parameter :: subname = 'mkpio_get_rawdata1d_real8' + !------------------------------------------------- + + rc = ESMF_SUCCESS + + ! Get data_i - Read in varname from filename + lsize = size(data_i) + + ! Create io descriptor for input raw data + ! This will query the raw data file for the dimensions of the variable varname and + ! create iodesc for either single or multi level input data + call mkpio_iodesc_rawdata(mesh_i, trim(varname), pioid, pio_varid, pio_vartype, pio_iodesc, rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + if (present(nt)) then + call pio_setframe(pioid, pio_varid, int(nt,kind=Pio_Offset_Kind)) + end if + + ! Read the input raw data + call ESMF_VMLogMemInfo("After mkpio_iodesc for varname for "//trim(varname)//" in "//trim(subname)) + if (pio_vartype == PIO_SHORT) then + allocate(data_short(lsize)) + call pio_read_darray(pioid, pio_varid, pio_iodesc, data_short, rcode) + data_i(:) = real(data_short(:), kind=r8) + deallocate(data_short) + else if (pio_vartype == PIO_INT) then + allocate(data_int(lsize)) + call pio_read_darray(pioid, pio_varid, pio_iodesc, data_int, rcode) + data_i(:) = real(data_int(:), kind=r8) + deallocate(data_int) + else if (pio_vartype == PIO_REAL) then + allocate(data_real(lsize)) + call pio_read_darray(pioid, pio_varid, pio_iodesc, data_real, rcode) + data_i(:) = real(data_real(:), kind=r8) + deallocate(data_real) + else if (pio_vartype == PIO_DOUBLE) then + call pio_read_darray(pioid, pio_varid, pio_iodesc, data_i, rcode) + else + call shr_sys_abort(subName//" ERROR: supported variable type not found for "//trim(varname)) + end if + call ESMF_VMLogMemInfo("After call to pio_read_darrayy for varname "//trim(varname)) + + call pio_freedecomp(pioid, pio_iodesc) + call ESMF_VMLogMemInfo("After call to pio_freedecomp for "//trim(varname)) + + end subroutine mkpio_get_rawdata1d_real8 + + !=============================================================== + subroutine mkpio_get_rawdata2d_real4(pioid, varname, mesh_i, data_i, rc) + + ! input/output variables + type(file_desc_t) , intent(inout) :: pioid + character(len=*) , intent(in) :: varname ! field name in rawdata file + type(ESMF_Mesh) , intent(in) :: mesh_i + real(r4) , intent(inout) :: data_i(:,:) ! input raw data + integer , intent(out) :: rc + + ! local variables + type(var_desc_t) :: pio_varid + integer :: pio_vartype + type(io_desc_t) :: pio_iodesc + real(r4), allocatable :: data_real1d(:) + real(r4), allocatable :: data_real2d(:,:) + real(r8), allocatable :: data_double1d(:) + real(r8), allocatable :: data_double2d(:,:) + real(r4), allocatable :: landmask(:) + integer :: lsize, nlev + integer :: n,l + integer :: rcode + character(len=*), parameter :: subname = ' mkpio_get_rawdata_2d' + !------------------------------------------------- + + rc = ESMF_SUCCESS + + ! Get data_i - Read in varname from filename + ! Note that data_i is coming in as (nlev,lsize) in terms of dimensions + nlev = size(data_i, dim=1) + lsize = size(data_i, dim=2) + + ! Create io descriptor for input raw data + ! This will query the raw data file for the dimensions of the variable varname and + ! create iodesc for either single or multi level input data + call ESMF_VMLogMemInfo("Before mkpio_iodesc in "//trim(subname)) + call mkpio_iodesc_rawdata(mesh_i, trim(varname), pioid, pio_varid, pio_vartype, pio_iodesc, rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After mkpio_iodesc in "//trim(subname)) + + ! Read the input raw data (all levels read at once) + ! - levels are the innermost dimension for esmf fields + ! - levels are the outermost dimension in pio reads + ! Input data is read into (lsize,nlev) array and then transferred to data_i(nlev,lsize) + if (pio_vartype == PIO_REAL) then + allocate(data_real2d(lsize,nlev)) + call pio_read_darray(pioid, pio_varid, pio_iodesc, data_real2d, rcode) + do l = 1,nlev + do n = 1,lsize + data_i(l,n) = data_real2d(n,l) + end do + end do + deallocate(data_real2d) + else if (pio_vartype == PIO_DOUBLE) then + allocate(data_double2d(lsize,nlev)) + call pio_read_darray(pioid, pio_varid, pio_iodesc, data_double2d, rcode) + do l = 1,nlev + do n = 1,lsize + data_i(l,n) = real(data_double2d(n,l), kind=r4) + end do + end do + deallocate(data_double2d) + else + call shr_sys_abort(subName//" ERROR: only real and double types are supported for "//trim(varname)) + end if + call pio_freedecomp(pioid, pio_iodesc) + + end subroutine mkpio_get_rawdata2d_real4 + + !=============================================================== + subroutine mkpio_get_rawdata2d_real8(pioid, varname, mesh_i, data_i, setframe, rc) + + ! input/output variables + type(file_desc_t) , intent(inout) :: pioid + character(len=*) , intent(in) :: varname ! field name in rawdata file + type(ESMF_Mesh) , intent(in) :: mesh_i + real(r8) , intent(inout) :: data_i(:,:) ! input raw data + integer, optional , intent(in) :: setframe + integer , intent(out) :: rc + + ! local variables + type(var_desc_t) :: pio_varid + integer :: pio_vartype + type(io_desc_t) :: pio_iodesc + type(io_desc_t) :: pio_iodesc_mask + real(r4), allocatable :: data_real1d(:) + real(r4), allocatable :: data_real2d(:,:) + real(r8), allocatable :: data_double1d(:) + real(r8), allocatable :: data_double2d(:,:) + real(r4), allocatable :: landmask(:) + integer :: lsize, nlev + integer :: n,l + integer :: rcode + character(len=*), parameter :: subname = ' mkpio_get_rawdata_2d' + !------------------------------------------------- + + rc = ESMF_SUCCESS + + ! Get data_i - Read in varname from filename + ! Note that data_i is coming in as (nlev,lsize) in terms of dimensions + nlev = size(data_i, dim=1) + lsize = size(data_i, dim=2) + + ! Create io descriptor for input raw data + ! This will query the raw data file for the dimensions of the variable varname and + ! create iodesc for either single or multi level input data + call ESMF_VMLogMemInfo("Before mkpio_iodesc in "//trim(subname)) + call mkpio_iodesc_rawdata(mesh_i, trim(varname), pioid, pio_varid, pio_vartype, pio_iodesc, rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After mkpio_iodesc in "//trim(subname)) + + ! Read the input raw data (all levels read at once) + ! - levels are the innermost dimension for esmf fields + ! - levels are the outermost dimension in pio reads + ! Input data is read into (lsize,nlev) array and then transferred to data_i(nlev,lsize) + if (pio_vartype == PIO_REAL) then + allocate(data_real2d(lsize,nlev)) + call pio_read_darray(pioid, pio_varid, pio_iodesc, data_real2d, rcode) + do l = 1,nlev + do n = 1,lsize + data_i(l,n) = real(data_real2d(n,l), kind=r8) + end do + end do + deallocate(data_real2d) + else if (pio_vartype == PIO_DOUBLE) then + allocate(data_double2d(lsize,nlev)) + call pio_read_darray(pioid, pio_varid, pio_iodesc, data_double2d, rcode) + do l = 1,nlev + do n = 1,lsize + data_i(l,n) = data_double2d(n,l) + end do + end do + deallocate(data_double2d) + else + call shr_sys_abort(subName//"ERROR: only real and double types are supported") + end if + call pio_freedecomp(pioid, pio_iodesc) + + end subroutine mkpio_get_rawdata2d_real8 + + !=============================================================== + subroutine mkpio_iodesc_rawdata( mesh, varname, pioid, pio_varid, pio_vartype, pio_iodesc, rc) + + ! Determine pio io descriptor for variable on rawdata file + + ! input/output variables + type(ESMF_Mesh) , intent(in) :: mesh + character(len=*) , intent(in) :: varname + type(file_desc_t) , intent(inout) :: pioid + type(var_desc_t) , intent(out) :: pio_varid + integer , intent(out) :: pio_vartype + type(io_desc_t) , intent(inout) :: pio_iodesc + integer , intent(out) :: rc + + ! local variables + type(ESMF_DistGrid) :: distGrid + integer :: n, ndims + integer, allocatable :: compdof(:) + integer, allocatable :: compdof3d(:) + integer, allocatable :: dimids(:) + integer, allocatable :: dimlens(:) + character(len=cs) :: dimname + integer :: lsize + integer :: nlev + integer :: cnt, m + integer :: offset + integer :: rCode ! pio return code (only used when pio error handling is PIO_BCAST_ERROR) + integer :: unlimdim + logical :: unlimited_dim + character(*), parameter :: subname = '(mkpio_iodesc_rawdata) ' + !------------------------------------------------------------------------------- + + rc = ESMF_SUCCESS + + call ESMF_VMLogMemInfo("Beginning setting compdof for "//trim(varname)) + call ESMF_MeshGet(mesh, elementdistGrid=distGrid, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_DistGridGet(distGrid, localDe=0, elementCount=lsize, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + allocate(compdof(lsize)) + call ESMF_DistGridGet(distGrid, localDe=0, seqIndexList=compdof, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("Ending setting compdof for "//trim(varname)) + + ! get pio variable id, type and number of dimensions + rcode = pio_inq_varid(pioid, trim(varname), pio_varid) + rcode = pio_inq_vartype(pioid, pio_varid, pio_vartype) + rcode = pio_inq_varndims(pioid, pio_varid, ndims) + + ! get variable dimension sizes + allocate(dimids(ndims)) + allocate(dimlens(ndims)) + rcode = pio_inq_vardimid(pioid, pio_varid, dimids(1:ndims)) + do n = 1, ndims + rcode = pio_inq_dimlen(pioid, dimids(n), dimlens(n)) + end do + rcode = pio_inq_unlimdim(pioid, unlimdim) + unlimited_dim = (dimids(ndims) == unlimdim) + + ! Create compdof3d if needed + ! Assume that input data is always lon,lat as first two dimensions + nlev = 0 + if (ndims == 3 .and. .not. unlimited_dim) then + nlev = dimlens(3) + else if (ndims == 3 .and. unlimited_dim) then + ! do nothing - keep nlev at 0 + else if (ndims == 4 .and. .not. unlimited_dim) then + nlev = dimlens(3)*dimlens(4) + else if (ndims == 4 .and. unlimited_dim) then + nlev = dimlens(3) + end if + + if (nlev > 0) then + offset = dimlens(1)*dimlens(2) + allocate(compdof3d(nlev*lsize)) + cnt = 0 + do n = 1,nlev + do m = 1,size(compdof) + cnt = cnt + 1 + compdof3d(cnt) = (n-1)*offset + compdof(m) + enddo + enddo + end if + + ! determine io descriptor for this variable + if (ndims == 1) then + call pio_initdecomp(pio_iosystem, pio_vartype, (/dimlens(1)/), compdof, pio_iodesc) + if (root_task .and. debug) then + write(ndiag,'(a,i20)') ' set iodesc for rawdata: '//trim(varname)//' with dim(1) = ',& + dimlens(1) + end if + else if (ndims == 2) then + call pio_initdecomp(pio_iosystem, pio_vartype, (/dimlens(1),dimlens(2)/), compdof, pio_iodesc) + if (root_task .and. debug) then + write(ndiag,'(a,i8,i8)') ' set iodesc for rawdata: '//trim(varname)//' with dim(1),dim(2) = ',& + dimlens(1),dimlens(2) + end if + else if (ndims == 3) then + if (unlimited_dim) then + call pio_initdecomp(pio_iosystem, pio_vartype, (/dimlens(1),dimlens(2)/), compdof, pio_iodesc) + if (root_task .and. debug) then + write(ndiag,'(a,i8,i8)') ' set iodesc for rawdata: '//trim(varname)//' with dim(1),dim(2) = ',& + dimlens(1),dimlens(2) + end if + else + call pio_initdecomp(pio_iosystem, pio_vartype, (/dimlens(1),dimlens(2),dimlens(3)/), compdof3d, pio_iodesc) + if (root_task .and. debug) then + write(ndiag,'(a,i8,i8,i8)') ' set iodesc for rawdata: '//trim(varname)//' with dim(1),dim(2),dim(3) = ',& + dimlens(1),dimlens(2),dimlens(3) + end if + end if + else if (ndims == 4) then + if (unlimited_dim) then + call pio_initdecomp(pio_iosystem, pio_vartype, (/dimlens(1),dimlens(2),dimlens(3)/), compdof3d, pio_iodesc) + if (root_task .and. debug) then + write(ndiag,'(a,i8,i8,i8)') ' set iodesc for rawdata: '//trim(varname)//' with dim(1),dim(2),dim(3) = ',& + dimlens(1),dimlens(2),dimlens(3) + end if + else + write(6,*)' ndims = ',ndims + write(6,*)' unlimited_dim = ',unlimited_dim + call shr_sys_abort('for lon/lat support up to 3 input spatial dims plus a time dim') + end if + else + call shr_sys_abort('rawdata input for variable '//trim(varname)//' must have ndims either 1,2,3 or 4') + end if + + ! deallocate memory + deallocate(compdof) + if (allocated(compdof3d)) deallocate(compdof3d) + call ESMF_VMLogMemInfo("Finished setting iodesc for "//trim(varname)//" in "//trim(subname)) + + end subroutine mkpio_iodesc_rawdata + + !=============================================================== + subroutine mkpio_iodesc_output(pioid, mesh, varname, pio_iodesc, rc) + + ! Create pio_iodesc for varname + + ! input/output variables + type(file_desc_t) , intent(inout) :: pioid + character(len=*) , intent(in) :: varname + type(ESMF_Mesh) , intent(in) :: mesh + type(io_desc_t) , intent(inout) :: pio_iodesc + integer , intent(out) :: rc + + ! local variables + type(ESMF_DistGrid) :: distGrid + integer :: n, ndims + integer, allocatable :: compdof(:) + integer, allocatable :: compdof3d(:) + integer, allocatable :: dimids(:) + integer, allocatable :: dimlens(:) + character(len=cs) :: dimname + integer :: lsize + integer :: nlev + integer :: cnt, m + integer :: offset + type(var_desc_t) :: pio_varid + integer :: pio_vartype + integer :: rCode ! pio return code (only used when pio error handling is PIO_BCAST_ERROR) + integer :: unlimdim + logical :: unlimited_dim + character(*), parameter :: subname = '(shr_strdata_set_stream_iodesc) ' + !------------------------------------------------------------------------------- + + rc = ESMF_SUCCESS + + ! get pio variable id, type and dimension information + rcode = pio_inq_varid(pioid, trim(varname), pio_varid) + rcode = pio_inq_vartype(pioid, pio_varid, pio_vartype) + rcode = pio_inq_varndims(pioid, pio_varid, ndims) + allocate(dimids(ndims)) + allocate(dimlens(ndims)) + rcode = pio_inq_vardimid(pioid, pio_varid, dimids(1:ndims)) + do n = 1, ndims + rcode = pio_inq_dimlen(pioid, dimids(n), dimlens(n)) + end do + rcode = pio_inq_unlimdim(pioid, unlimdim) + unlimited_dim = (dimids(ndims) == unlimdim) + + ! Get compdof from mesh + call ESMF_MeshGet(mesh, elementdistGrid=distGrid, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_DistGridGet(distGrid, localDe=0, elementCount=lsize, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + allocate(compdof(lsize)) + call ESMF_DistGridGet(distGrid, localDe=0, seqIndexList=compdof, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Create compdof3d if needed + nlev = 0 + if (outnc_1d) then + offset = dimlens(1) + if (ndims == 2 .and. .not. unlimited_dim) then + nlev = dimlens(2) + else if (ndims == 3 .and. unlimited_dim) then + nlev = dimlens(2) + else if (ndims == 3 .and. .not. unlimited_dim) then + nlev = dimlens(2)*dimlens(3) + end if + else + offset = dimlens(1)*dimlens(2) + if (ndims == 3 .and. .not. unlimited_dim) then + nlev = dimlens(3) + else if (ndims == 3 .and. unlimited_dim) then + ! do nothing - keep nlev at 0 + else if (ndims == 4 .and. .not. unlimited_dim) then + nlev = dimlens(3)*dimlens(4) + else if (ndims == 4 .and. unlimited_dim) then + nlev = dimlens(3) + end if + end if + + if (nlev > 0) then + allocate(compdof3d(nlev*lsize)) + cnt = 0 + do n = 1,nlev + do m = 1,size(compdof) + cnt = cnt + 1 + compdof3d(cnt) = (n-1)*offset + compdof(m) + enddo + enddo + end if + + ! determine io descriptor for this variable + if (outnc_1d) then + ! Assume that can have (gridcell), (gridcell,lev), (gridcell,lev,time) + ! Where lev would correspond to an undistributed dimension in esmf + if (ndims == 1) then + call pio_initdecomp(pio_iosystem, pio_vartype, (/dimlens(1)/), compdof, pio_iodesc) + if (root_task .and. debug) then + write(ndiag,'(a,i20)') ' set iodesc for output data: '//trim(varname)//' with dim(1) = ',& + dimlens(1) + end if + else if (ndims == 2) then + if (unlimited_dim) then + call pio_initdecomp(pio_iosystem, pio_vartype, (/dimlens(1)/), compdof, pio_iodesc) + if (root_task .and. debug) then + write(ndiag,'(a,i8)') ' set iodesc for output data with time dim: '//trim(varname)//& + ' with dim(1) = ',dimlens(1) + end if + else + call pio_initdecomp(pio_iosystem, pio_vartype, (/dimlens(1),dimlens(2)/), compdof3d, pio_iodesc) + if (root_task .and. debug) then + write(ndiag,'(a,i8,i8)') ' set iodesc for output data: '//trim(varname)//& + ' with dim(1),dim(2) = ',dimlens(1),dimlens(2) + end if + end if + else if (ndims == 3) then + if (unlimited_dim) then + call pio_initdecomp(pio_iosystem, pio_vartype, (/dimlens(1),dimlens(2)/), compdof3d, pio_iodesc) + if (root_task .and. debug) then + write(ndiag,'(a,i8,i8)') ' set iodesc for output data with time dim: '//trim(varname)//& + ' with dim(1),dim(2) = ',dimlens(1),dimlens(2) + end if + else + call pio_initdecomp(pio_iosystem, pio_vartype, (/dimlens(1),dimlens(2),dimlens(3)/), compdof3d, pio_iodesc) + if (root_task .and. debug) then + write(ndiag,'(a,i8,i8,i8)') ' set iodesc for output data: '//trim(varname)//& + ' with dim(1),dim(2),dim(3) = ',dimlens(1),dimlens(2),dimlens(3) + end if + end if + end if + else + ! Assume that can have (lon,lat), (lon,lat,lev1), (lon,lat,lev1,lev2), (lon,lat,time) or (lon,lat,lev1,time) + if (ndims == 2) then + call pio_initdecomp(pio_iosystem, pio_vartype, (/dimlens(1),dimlens(2)/), compdof, pio_iodesc) + if (root_task .and. debug) then + write(ndiag,'(a,i8,i8)') ' set iodesc for output data: '//trim(varname)//& + ' with dim(1),dim(2)= ',dimlens(1),dimlens(2) + end if + else if (ndims == 3) then + if (unlimited_dim) then + call pio_initdecomp(pio_iosystem, pio_vartype, (/dimlens(1),dimlens(2)/), compdof, pio_iodesc) + if (root_task .and. debug) then + write(ndiag,'(a,i8,i8)') ' set iodesc for output data with time dim : '//trim(varname)//& + ' with dim(1),dim(2)= ', dimlens(1),dimlens(2) + end if + else + call pio_initdecomp(pio_iosystem, pio_vartype, (/dimlens(1),dimlens(2),dimlens(3)/), compdof3d, pio_iodesc) + if (root_task .and. debug) then + write(ndiag,'(a,i8,i8,i8)') ' set iodesc for output data: '//trim(varname)//& + ' with dim(1),dim(2),dim3(3)= ',dimlens(1),dimlens(2),dimlens(3) + end if + end if + else if (ndims == 4) then + if (unlimited_dim) then + call pio_initdecomp(pio_iosystem, pio_vartype, (/dimlens(1),dimlens(2),dimlens(3)/), compdof3d, pio_iodesc) + if (root_task .and. debug) then + write(ndiag,'(a,i8,i8,i8)') ' set iodesc for output data with time dim : '//trim(varname)//& + ' with dim(1),dim(2),dimlens(3)= ', dimlens(1),dimlens(2),dimlens(3) + end if + else + call pio_initdecomp(pio_iosystem, pio_vartype, (/dimlens(1),dimlens(2),dimlens(3),dimlens(4)/), compdof3d, pio_iodesc) + if (root_task .and. debug) then + write(ndiag,'(a,i8,i8,i8,i8)') ' set iodesc for output data: '//trim(varname)//& + ' with dim(1),dim(2),dimlens(3),dimlens(4)= ', dimlens(1),dimlens(2),dimlens(3),dimlens(4) + end if + end if + end if + end if + + ! deallocate memory + deallocate(compdof) + if (allocated(compdof3d)) deallocate(compdof3d) + + end subroutine mkpio_iodesc_output + + !=============================================================================== + logical function mkpio_file_exists(filename) + + !--------------- + ! inquire if i/o file exists + !--------------- + + ! input/output variables + character(len=*) , intent(in) :: filename + + ! local variables + integer :: tmp(1) + integer :: ier + !------------------------------------------------------------------------------- + + tmp(1) = 0 + mkpio_file_exists = .false. + if (root_task) then + inquire(file=trim(filename), exist=mkpio_file_exists) + if (mkpio_file_exists) tmp(1) = 1 + end if + call mpi_bcast(tmp(1), 1, MPI_INTEGER, 0, mpicom, ier) + if (tmp(1) == 1) mkpio_file_exists = .true. + + end function mkpio_file_exists + + !=============================================================================== + subroutine mkpio_wopen(filename, clobber, pioid) + + !--------------- + ! open netcdf file + !--------------- + + use pio , only : PIO_IOTYPE_PNETCDF, PIO_IOTYPE_NETCDF, PIO_BCAST_ERROR, PIO_INTERNAL_ERROR + use pio , only : pio_openfile, pio_createfile, PIO_GLOBAL, pio_enddef + use pio , only : pio_put_att, pio_get_att + use pio , only : pio_seterrorhandling, pio_file_is_open, pio_clobber, pio_write, pio_noclobber + + ! input/output arguments + character(len=*) , intent(in) :: filename + logical , intent(in) :: clobber + type(file_desc_t) , intent(inout) :: pioid + + ! local variables + integer :: rcode + integer :: nmode + character(*),parameter :: subName = '(mkpio_wopen) ' + !------------------------------------------------------------------------------- + + ! filename not open + if (root_task) then + write(ndiag,'(a)') "opening output file "//trim(filename) + end if + + if (mkpio_file_exists(filename)) then + if (clobber) then + nmode = pio_clobber + ! only applies to classic NETCDF files. + if(pio_iotype == PIO_IOTYPE_NETCDF .or. pio_iotype == PIO_IOTYPE_PNETCDF) then + nmode = ior(nmode,pio_ioformat) + endif + rcode = pio_createfile(pio_iosystem, pioid, pio_iotype, trim(filename), nmode) + if (root_task) write(ndiag,'(a)') trim(subname)//' creating file '//trim(filename) + else + rcode = pio_openfile(pio_iosystem, pioid, pio_iotype, trim(filename), pio_write) + if (root_task) write(ndiag,'(a)') trim(subname)//' opening file '//trim(filename) + endif + else + ! only applies to classic NETCDF files. + nmode = pio_noclobber + if (pio_iotype == PIO_IOTYPE_NETCDF .or. pio_iotype == PIO_IOTYPE_PNETCDF) then + nmode = ior(nmode,pio_ioformat) + endif + rcode = pio_createfile(pio_iosystem, pioid, pio_iotype, trim(filename), nmode) + if (root_task) write(ndiag,'(a)') trim(subname) //' creating file '// trim(filename) + endif + call ESMF_LogWrite("successfully opened output file "//trim(filename), ESMF_LOGMSG_INFO) + + end subroutine mkpio_wopen + + !=============================================================================== + subroutine mkpio_close(pioid, filename, rc) + + !--------------- + ! close netcdf file + !--------------- + + use pio, only: pio_file_is_open, pio_closefile + + ! input/output variables + type(file_desc_t) , intent(in) :: pioid + character(*) , intent(in) :: filename + integer , intent(out) :: rc + + ! local variables + character(len=CL) :: wfilename + character(*),parameter :: subName = '(mkpio_close) ' + !------------------------------------------------------------------------------- + + rc = ESMF_SUCCESS + + if (.not. pio_file_is_open(pioid)) then + ! filename not open, just return + elseif (trim(wfilename) == trim(filename)) then + ! filename matches, close it + call pio_closefile(pioid) + else + ! different filename is open, abort + if (root_task) then + write(ndiag,'(a)') trim(subname)//' different wfilename and filename currently open, aborting ' + write(ndiag,'(a)') 'filename = ',trim(filename) + write(ndiag,'(a)') 'wfilename = ',trim(wfilename) + end if + call ESMF_LogWrite(subname//'different file currently open, aborting '//trim(filename), ESMF_LOGMSG_INFO) + rc = ESMF_FAILURE + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=u_FILE_u)) then + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + endif + + end subroutine mkpio_close + + !=============================================================================== + subroutine mkpio_defvar(pioid, varname, xtype, & + dim1name, dim2name, dim3name, dim4name, dim5name, & + long_name, units, missing_value, fill_value, imissing_value, ifill_value) + + ! Define a pio variable + + ! input/output variables + type(file_desc_t) , intent(in) :: pioid + character(len=*) , intent(in) :: varname ! variable name + integer , intent(in) :: xtype ! external type + character(len=*) , intent(in), optional :: dim1name ! dimension name + character(len=*) , intent(in), optional :: dim2name ! dimension name + character(len=*) , intent(in), optional :: dim3name ! dimension name + character(len=*) , intent(in), optional :: dim4name ! dimension name + character(len=*) , intent(in), optional :: dim5name ! dimension name + character(len=*) , intent(in), optional :: long_name ! attribute + character(len=*) , intent(in), optional :: units ! attribute + real(r8) , intent(in), optional :: missing_value ! attribute for real + real(r8) , intent(in), optional :: fill_value ! attribute for real + integer , intent(in), optional :: imissing_value ! attribute for int + integer , intent(in), optional :: ifill_value ! attribute for int + + ! !LOCAL VARIABLES: + integer :: n ! indices + integer :: ndims ! dimension counter + integer :: dimid(5) ! dimension ids + type(var_desc_t) :: pio_varid ! variable id + integer :: itmp ! temporary + character(len=CS) :: str ! temporary + integer :: rcode + character(*), parameter :: subname='mkpio_defvar_real' ! subroutine name + !----------------------------------------------------------------------- + + ! Determine dimension ids for variable + + dimid(:) = 0 + + if (present(dim1name)) then + rcode = pio_inq_dimid(pioid, dim1name, dimid(1)) + end if + if (present(dim2name)) then + rcode = pio_inq_dimid(pioid, dim2name, dimid(2)) + end if + if (present(dim3name)) then + rcode = pio_inq_dimid(pioid, dim3name, dimid(3)) + end if + if (present(dim4name)) then + rcode = pio_inq_dimid(pioid, dim4name, dimid(4)) + end if + if (present(dim5name)) then + rcode = pio_inq_dimid(pioid, dim5name, dimid(5)) + end if + + ! Define variable + if (present(dim1name)) then + ndims = 0 + do n = 1, size(dimid) + if (dimid(n) /= 0) ndims = ndims + 1 + end do + rcode = pio_def_var(pioid, trim(varname), xtype, dimid(1:ndims), pio_varid) + else + rcode = pio_def_var(pioid, trim(varname), xtype, pio_varid) + end if + + ! Add attributes to variable + if (present(long_name)) then + rcode = pio_put_att(pioid, pio_varid, 'long_name', trim(long_name)) + end if + if (present(units)) then + rcode = pio_put_att(pioid, pio_varid, 'units', trim(units)) + end if + if (present(fill_value)) then + rcode = pio_put_att(pioid, pio_varid, '_FillValue', fill_value) + end if + if (present(missing_value)) then + rcode = pio_put_att(pioid, pio_varid, 'missing_value', missing_value) + end if + if (present(ifill_value)) then + rcode = pio_put_att(pioid, pio_varid, '_FillValue', ifill_value) + end if + if (present(imissing_value)) then + rcode = pio_put_att(pioid, pio_varid, 'missing_value', imissing_value) + end if + + end subroutine mkpio_defvar + + ! ======================================================================== + ! mkpio_def_spatial_var routines: define a spatial pio variable + ! (convenience wrapper to mkpio_defvar) + ! ======================================================================== + + subroutine mkpio_def_spatial_var_0lev(pioid, varname, xtype, long_name, units) + + ! Define a spatial netCDF variable (convenience wrapper to mkpio_defvar) + ! The variable in question has ONLY spatial dimensions (no level or time dimensions) + + ! !ARGUMENTS: + type(file_desc_t) , intent(in) :: pioid + character(len=*) , intent(in) :: varname ! variable name + integer , intent(in) :: xtype ! external type + character(len=*) , intent(in) :: long_name ! attribute + character(len=*) , intent(in) :: units ! attribute + + ! !LOCAL VARIABLES: + character(len=*), parameter :: subname = 'mkpio_def_spatial_var_0lev' + !----------------------------------------------------------------------- + + if (outnc_1d) then + call mkpio_defvar(pioid=pioid, varname=varname, xtype=xtype, & + dim1name='gridcell', long_name=long_name, units=units) + else + call mkpio_defvar(pioid=pioid, varname=varname, xtype=xtype, & + dim1name='lsmlon', dim2name='lsmlat', long_name=long_name, units=units) + end if + + end subroutine mkpio_def_spatial_var_0lev + + !----------------------------------------------------------------------- + subroutine mkpio_def_spatial_var_1lev(pioid, varname, xtype, lev1name, long_name, units) + ! + ! Define a spatial netCDF variable (convenience wrapper to mkpio_defvar) + ! The variable in question has one level (or time) dimension in addition to its + ! spatial dimensions + + ! input/output variables + type(file_desc_t) , intent(in) :: pioid + character(len=*) , intent(in) :: varname ! variable name + integer , intent(in) :: xtype ! external type + character(len=*) , intent(in) :: lev1name ! name of level (or time) dimension + character(len=*) , intent(in) :: long_name ! attribute + character(len=*) , intent(in) :: units ! attribute + + ! local variables + character(len=*), parameter :: subname = 'mkpio_def_spatial_var_1lev' + !----------------------------------------------------------------------- + + if (outnc_1d) then + call mkpio_defvar(pioid, varname=varname, xtype=xtype, & + dim1name='gridcell', dim2name=lev1name, & + long_name=long_name, units=units) + else + call mkpio_defvar(pioid, varname=varname, xtype=xtype, & + dim1name='lsmlon', dim2name='lsmlat',dim3name=lev1name, & + long_name=long_name, units=units) + end if + + end subroutine mkpio_def_spatial_var_1lev + + !----------------------------------------------------------------------- + subroutine mkpio_def_spatial_var_2lev(pioid, varname, xtype, lev1name, lev2name, long_name, units) + ! + ! Define a spatial netCDF variable (convenience wrapper to mkpio_defvar) + ! + ! The variable in question has two level (or time) dimensions in addition to its + ! spatial dimensions + ! + ! input/output variables + type(file_desc_t) , intent(in) :: pioid + character(len=*) , intent(in) :: varname ! variable name + integer , intent(in) :: xtype ! external type + character(len=*) , intent(in) :: lev1name ! name of first level (or time) dimension + character(len=*) , intent(in) :: lev2name ! name of second level (or time) dimension + character(len=*) , intent(in) :: long_name ! attribute + character(len=*) , intent(in) :: units ! attribute + + ! local variables: + character(len=*), parameter :: subname = 'mkpio_def_spatial_var_2lev' + !----------------------------------------------------------------------- + + if (outnc_1d) then + call mkpio_defvar(pioid=pioid, varname=varname, xtype=xtype, & + dim1name='gridcell', dim2name=lev1name, dim3name=lev2name, & + long_name=long_name, units=units) + else + call mkpio_defvar(pioid=pioid, varname=varname, xtype=xtype, & + dim1name='lsmlon', dim2name='lsmlat', dim3name=lev1name, dim4name=lev2name, & + long_name=long_name, units=units) + end if + + end subroutine mkpio_def_spatial_var_2lev + + ! ======================================================================== + subroutine mkpio_put_time_slice_1d(pioid, pio_varid, pio_iodesc, time_index, data) + + ! Write a single time slice of a 1-d variable + + ! input/output variables + type(file_desc_t) , intent(inout) :: pioid + type(var_desc_t) , intent(inout) :: pio_varid + type(io_desc_t) , intent(inout) :: pio_iodesc + integer , intent(in) :: time_index ! time index in file + real(r8) , intent(in) :: data(:) ! data to write (a single time slice) + ! + ! local variables: + integer :: rcode + character(len=*), parameter :: subname = 'mkpio_put_time_slice_1d' + !----------------------------------------------------------------------- + + call pio_setframe(pioid, pio_varid, int(time_index, kind=Pio_Offset_Kind)) + call pio_write_darray(pioid, pio_varid, pio_iodesc, data, rcode) + + end subroutine mkpio_put_time_slice_1d + + ! ======================================================================== + subroutine mkpio_put_time_slice_2d(pioid, pio_varid, pio_iodesc, time_index, data) + + ! Write a single time slice of a 2-d variable + + ! input/output variables + type(file_desc_t) , intent(inout) :: pioid + type(var_desc_t) , intent(inout) :: pio_varid + type(io_desc_t) , intent(inout) :: pio_iodesc + integer , intent(in) :: time_index ! time index in file + real(r8) , intent(in) :: data(:,:) ! data to write (a single time slice) + ! + ! local variables: + integer :: rcode + character(len=*), parameter :: subname = 'mkpio_put_time_slice_2d' + !----------------------------------------------------------------------- + + call pio_setframe(pioid, pio_varid, int(time_index, kind=Pio_Offset_Kind)) + call pio_write_darray(pioid, pio_varid, pio_iodesc, data, rcode) + + end subroutine mkpio_put_time_slice_2d + + !=============================================================== + subroutine mkpio_get_dimlengths(pioid, varname, ndims, dimlengths) + + ! Returns the number of dimensions and an array containing the dimension lengths of a + ! variable in an open netcdf file. + ! Entries 1:ndims in the returned dim_lengths array contain the dimension lengths; the + ! remaining entries in that vector are meaningless. The dim_lengths array must be large + ! enough to hold all ndims values; if not, the code aborts (this can be ensured by passing + ! in an array of length nf_max_var_dims). + ! + ! input/otuput variables + type(file_desc_t) , intent(in) :: pioid + character(len=*) , intent(in) :: varname ! name of variable of interest + integer , intent(out) :: ndims ! number of dimensions of variable + integer , intent(out) :: dimlengths(:) ! lengths of dimensions of variable + ! + ! local variables + type(var_desc_t) :: pio_varid + integer, allocatable :: dimids(:) + integer :: i + integer :: rcode + character(len=*), parameter :: subname = 'mkpio_get_dimlengths' + !------------------------------------------------------------------------------ + + rcode = pio_inq_varid(pioid, trim(varname), pio_varid) + rcode = pio_inq_varndims(pioid, pio_varid, ndims) + + if (ndims > size(dimlengths)) then + call shr_sys_abort(trim(subname)//' ERROR: dimlengths too small') + end if + + allocate(dimids(ndims)) + rcode = pio_inq_vardimid(pioid, pio_varid, dimids(1:ndims)) + dimlengths(:) = 0 ! pre-fill with 0 so we won't have garbage in elements past ndims + do i = 1, ndims + rcode = pio_inq_dimlen(pioid, dimids(i), dimlengths(i)) + end do + deallocate(dimids) + + end subroutine mkpio_get_dimlengths + + ! ======================================================================== + subroutine mkpio_get_rawdata1d_level_real4(pioid, pio_iodesc, unlimited_index, varname, data_i) + + ! input/output variables + type(file_desc_t), intent(inout) :: pioid + type(io_desc_t) , intent(inout) :: pio_iodesc + integer , intent(in) :: unlimited_index + character(len=*) , intent(in) :: varname ! field name in rawdata file + real(r4) , intent(inout) :: data_i(:) ! input raw data + + ! local variables + type(var_desc_t) :: pio_varid + integer :: pio_vartype + integer(i2) , allocatable :: data_short(:) + integer(i4) , allocatable :: data_int(:) + real(r8) , allocatable :: data_double(:) + integer :: ns_i + integer :: rcode + character(len=*), parameter :: subname = 'mkpio_get_rawdata_level_real4' + !------------------------------------------------- + + ! Get variable id and type + rcode = pio_inq_varid(pioid, trim(varname), pio_varid) + rcode = pio_inq_vartype(pioid, pio_varid, pio_vartype) + + ! Set unlimited frame index + call pio_setframe(pioid, pio_varid, int(unlimited_index, kind=Pio_Offset_Kind)) + + ! Read the input raw data + ns_i = size(data_i) + if (pio_vartype == PIO_SHORT) then + allocate(data_short(ns_i)) + call pio_read_darray(pioid, pio_varid, pio_iodesc, data_short, rcode) + data_i(:) = real(data_short(:), kind=r8) + deallocate(data_short) + else if (pio_vartype == PIO_INT) then + allocate(data_int(ns_i)) + call pio_read_darray(pioid, pio_varid, pio_iodesc, data_int, rcode) + data_i(:) = real(data_int(:), kind=r4) + deallocate(data_int) + else if (pio_vartype == PIO_REAL) then + call pio_read_darray(pioid, pio_varid, pio_iodesc, data_i, rcode) + else if (pio_vartype == PIO_DOUBLE) then + ns_i = size(data_i) + allocate(data_double(ns_i)) + call pio_read_darray(pioid, pio_varid, pio_iodesc, data_double, rcode) + data_i(:) = real(data_double(:), kind=r4) + deallocate(data_double) + else + call shr_sys_abort(subName//" ERROR: vartype not supported for "//trim(varname)) + end if + call ESMF_VMLogMemInfo("After call to pio_read_darray for varname "//trim(varname)) + + end subroutine mkpio_get_rawdata1d_level_real4 + + ! ======================================================================== + subroutine mkpio_get_rawdata1d_level_real8(pioid, pio_iodesc, unlimited_index, varname, data_i) + + ! input/output variables + type(file_desc_t), intent(inout) :: pioid + type(io_desc_t) , intent(inout) :: pio_iodesc + integer , intent(in) :: unlimited_index + character(len=*) , intent(in) :: varname ! field name in rawdata file + real(r8) , intent(inout) :: data_i(:) ! input raw data + + ! local variables + type(var_desc_t) :: pio_varid + integer :: pio_vartype + integer(i2) , allocatable :: data_short(:) + integer(i4) , allocatable :: data_int(:) + real(r4) , allocatable :: data_real(:) + integer :: ns_i + integer :: rcode + character(len=*), parameter :: subname = 'mkpio_get_rawdata1d_real4' + !------------------------------------------------- + + ! Get variable id and type + rcode = pio_inq_varid(pioid, trim(varname), pio_varid) + rcode = pio_inq_vartype(pioid, pio_varid, pio_vartype) + + ! Set unlimited frame index + call pio_setframe(pioid, pio_varid, int(unlimited_index, kind=Pio_Offset_Kind)) + + ! Read the input raw data + ns_i = size(data_i) + if (pio_vartype == PIO_SHORT) then + allocate(data_short(ns_i)) + call pio_read_darray(pioid, pio_varid, pio_iodesc, data_short, rcode) + data_i(:) = real(data_short(:), kind=r8) + deallocate(data_short) + else if (pio_vartype == PIO_INT) then + allocate(data_int(ns_i)) + call pio_read_darray(pioid, pio_varid, pio_iodesc, data_int, rcode) + data_i(:) = real(data_int(:), kind=r4) + deallocate(data_int) + else if (pio_vartype == PIO_REAL) then + allocate(data_real(ns_i)) + call pio_read_darray(pioid, pio_varid, pio_iodesc, data_real, rcode) + data_i(:) = real(data_real(:), kind=r8) + deallocate(data_real) + else if (pio_vartype == PIO_DOUBLE) then + call pio_read_darray(pioid, pio_varid, pio_iodesc, data_i, rcode) + else + call shr_sys_abort(subName//" ERROR: vartype not supported for "//trim(varname)) + end if + call ESMF_VMLogMemInfo("After call to pio_read_darray for varname "//trim(varname)) + + end subroutine mkpio_get_rawdata1d_level_real8 + + ! ======================================================================== + subroutine mkpio_get_rawdata2d_level_real8(pioid, pio_iodesc, unlimited_index, varname, data_i) + + ! input/output variables + type(file_desc_t), intent(inout) :: pioid + type(io_desc_t) , intent(inout) :: pio_iodesc + integer , intent(in) :: unlimited_index + character(len=*) , intent(in) :: varname ! field name in rawdata file + real(r8) , intent(inout) :: data_i(:,:) ! input raw data + + ! local variables + type(var_desc_t) :: pio_varid + integer :: pio_vartype + integer(i2) , allocatable :: data_short2d(:,:) + integer(i4) , allocatable :: data_int2d(:,:) + real(r4) , allocatable :: data_real2d(:,:) + real(r8) , allocatable :: data_double2d(:,:) + integer :: ns_i, nlev + integer :: n, l + integer :: rcode + character(len=*), parameter :: subname = 'mkpio_get_rawdata1d_real4' + !------------------------------------------------- + + ! Get variable id and type + rcode = pio_inq_varid(pioid, trim(varname), pio_varid) + rcode = pio_inq_vartype(pioid, pio_varid, pio_vartype) + + ! Set unlimited frame index + call pio_setframe(pioid, pio_varid, int(unlimited_index, kind=Pio_Offset_Kind)) + + ! Read the input raw data + ! - levels are the innermost dimension for esmf fields + ! - levels are the outermost dimension in pio reads + ! Input data is read into (ns_i,nlev) array and then transferred to data_i(nlev,ns_i) + ! which sill be used for esmf regridding + nlev = size(data_i, dim=1) + ns_i = size(data_i, dim=2) + if (pio_vartype == PIO_SHORT) then + allocate(data_short2d(ns_i,nlev)) + call pio_read_darray(pioid, pio_varid, pio_iodesc, data_short2d, rcode) + do l = 1,nlev + do n = 1,ns_i + data_i(l,n) = real(data_short2d(n,l), kind=r8) + end do + end do + deallocate(data_short2d) + else if (pio_vartype == PIO_INT) then + allocate(data_int2d(ns_i,nlev)) + call pio_read_darray(pioid, pio_varid, pio_iodesc, data_int2d, rcode) + do l = 1,nlev + do n = 1,ns_i + data_i(l,n) = real(data_int2d(n,l), kind=r8) + end do + end do + deallocate(data_int2d) + else if (pio_vartype == PIO_REAL) then + allocate(data_real2d(ns_i,nlev)) + call pio_read_darray(pioid, pio_varid, pio_iodesc, data_real2d, rcode) + do l = 1,nlev + do n = 1,ns_i + data_i(l,n) = real(data_real2d(n,l), kind=r8) + end do + end do + deallocate(data_real2d) + else if (pio_vartype == PIO_DOUBLE) then + allocate(data_double2d(ns_i,nlev)) + call pio_read_darray(pioid, pio_varid, pio_iodesc, data_double2d, rcode) + do l = 1,nlev + do n = 1,ns_i + data_i(l,n) = data_double2d(n,l) + end do + end do + deallocate(data_double2d) + else + call shr_sys_abort(subName//" ERROR: vartype not supported for "//trim(varname)) + end if + call ESMF_VMLogMemInfo("After call to pio_read_darray for varname "//trim(varname)) + + end subroutine mkpio_get_rawdata2d_level_real8 + +end module mkpioMod diff --git a/tools/mksurfdata_esmf/src/mksoilcolMod.F90 b/tools/mksurfdata_esmf/src/mksoilcolMod.F90 new file mode 100644 index 0000000000..6fa9600f3c --- /dev/null +++ b/tools/mksurfdata_esmf/src/mksoilcolMod.F90 @@ -0,0 +1,327 @@ +module mksoilcolMod + + use ESMF + use pio , only : file_desc_t, pio_openfile, pio_closefile, pio_nowrite + use pio , only : pio_syncfile, pio_inq_varid, pio_put_var, var_desc_t + use shr_kind_mod , only : r8 => shr_kind_r8, r4 => shr_kind_r4 + use shr_sys_mod , only : shr_sys_abort + use mkpioMod , only : mkpio_get_rawdata, pio_iotype, pio_iosystem + use mkvarctl , only : root_task, ndiag, mpicom, unsetcol + use mkdiagnosticsMod , only : output_diagnostics_index + use mkutilsMod , only : chkerr + use mkfileMod , only : mkfile_output + + implicit none + private + +#include + + public :: mksoilcol ! Set soil colors + private :: get_dominant_soilcol + + integer :: num_soilcolors + type(ESMF_DynamicMask) :: dynamicMask + + character(len=*) , parameter :: u_FILE_u = & + __FILE__ + +!================================================================================= +contains +!================================================================================= + + subroutine mksoilcol(file_data_i, file_mesh_i, mesh_o, pioid_o, rc) + + ! input/output variables + character(len=*) , intent(in) :: file_mesh_i ! input mesh file name + character(len=*) , intent(in) :: file_data_i ! input data file name + type(ESMF_Mesh) , intent(in) :: mesh_o ! model mesho + type(file_desc_t) , intent(inout) :: pioid_o + integer , intent(out) :: rc + + ! local variables: + type(ESMF_RouteHandle) :: routehandle + type(ESMF_Mesh) :: mesh_i + type(ESMF_Field) :: field_i + type(ESMF_Field) :: field_o + type(ESMF_Field) :: field_dstfrac + type(file_desc_t) :: pioid_i + type(var_desc_t) :: pio_varid + integer :: ni,no, k + integer :: ns_i, ns_o + integer , allocatable :: mask_i(:) + real(r4), allocatable :: rmask_i(:) + real(r8), allocatable :: frac_o(:) + real(r4), allocatable :: soil_color_i(:) + integer , allocatable :: soil_color_o(:) ! soil color classes + integer :: nsoilcol ! number of soil colors + real(r4), pointer :: dataptr(:) + real(r8), pointer :: dataptr_r8(:) + integer :: nsoilcol_local + integer :: rcode, ier + integer :: srcTermProcessing_Value = 0 + character(len=*), parameter :: subname = 'mksoilcol' + !----------------------------------------------------------------------- + + rc = ESMF_SUCCESS + + ! Note soil_color_override has been removed - instead should now use tools + ! subset_data and modify_fsurdat + + if (root_task) then + write(ndiag,*) + write(ndiag,'(1x,80a1)') ('=',k=1,80) + write(ndiag,*) + write(ndiag,'(a)') 'Attempting to make soil color classes .....' + write(ndiag,'(a)') ' Input file is '//trim(file_data_i) + write(ndiag,'(a)') ' Input mesh file is '//trim(file_mesh_i) + end if + + ! Open soil color data file + call ESMF_VMLogMemInfo("Before pio_openfile for "//trim(file_data_i)) + rcode = pio_openfile(pio_iosystem, pioid_i, pio_iotype, trim(file_data_i), pio_nowrite) + + ! Read in input mesh + call ESMF_VMLogMemInfo("Before create mesh_i in "//trim(subname)) + mesh_i = ESMF_MeshCreate(filename=trim(file_mesh_i), fileformat=ESMF_FILEFORMAT_ESMFMESH, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After create mesh_i in "//trim(subname)) + + ! Determine ns_i + call ESMF_MeshGet(mesh_i, numOwnedElements=ns_i, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Determine ns_o and allocate output data + call ESMF_MeshGet(mesh_o, numOwnedElements=ns_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + allocate (soil_color_o(ns_o)); soil_color_o(:) = -999 + + ! Get the landmask from the file and reset the mesh mask based on that + allocate(rmask_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort() + allocate(mask_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort() + call mkpio_get_rawdata(pioid_i, 'LANDMASK', mesh_i, rmask_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + do ni = 1,ns_i + if (rmask_i(ni) > 0._r4) then + mask_i(ni) = 1 + else + mask_i(ni) = 0 + end if + end do + deallocate(rmask_i) + call ESMF_MeshSet(mesh_i, elementMask=mask_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! Read in input soil color data + allocate(soil_color_i(ns_i),stat=ier) + if (ier/=0) call shr_sys_abort() + call mkpio_get_rawdata(pioid_i, 'SOIL_COLOR', mesh_i, soil_color_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After mkpio_getrawdata in "//trim(subname)) + + ! Scale the input soil color by the input mask + do ni = 1,ns_i + if (mask_i(ni) == 0) then + soil_color_i(ni) = 0._r4 + end if + end do + + ! Determine maximum number of soil colors across all processors + nsoilcol_local = maxval(soil_color_i) + call mpi_allreduce(nsoilcol_local, nsoilcol, 1, MPI_INTEGER, MPI_MAX, mpicom, rcode) + + ! Set module variable (used in the get_dominant_soilcol routine) + num_soilcolors = nsoilcol + + ! Create ESMF fields that will be used below + field_i = ESMF_FieldCreate(mesh_i, ESMF_TYPEKIND_R4, meshloc=ESMF_MESHLOC_ELEMENT, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + field_o = ESMF_FieldCreate(mesh_o, ESMF_TYPEKIND_R4, meshloc=ESMF_MESHLOC_ELEMENT, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + field_dstfrac = ESMF_FieldCreate(mesh_o, ESMF_TYPEKIND_R8, meshloc=ESMF_MESHLOC_ELEMENT, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! Create a route handle + call ESMF_FieldRegridStore(field_i, field_o, routehandle=routehandle, & + regridmethod=ESMF_REGRIDMETHOD_CONSERVE, srcTermProcessing=srcTermProcessing_Value, & + ignoreDegenerate=.true., unmappedaction=ESMF_UNMAPPEDACTION_IGNORE, & + dstFracField= field_dstfrac, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After regridstore in "//trim(subname)) + + ! Determine frac_o + call ESMF_FieldGet(field_dstfrac, farrayptr=dataptr_r8, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + allocate(frac_o(ns_o)) + frac_o(:) = dataptr_r8(:) + + ! Create a dynamic mask object + ! The dynamic mask object further holds a pointer to the routine that will be called in order to + ! handle dynamically masked elements - in this case its DynMaskProc (see below) + call ESMF_DynamicMaskSetR4R8R4(dynamicMask, dynamicMaskRoutine=get_dominant_soilcol, & + dynamicSrcMaskValue=0._r4, handleAllElements=.true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! Determine dominant soil color in the field regrid call below + call ESMF_FieldGet(field_i, farrayptr=dataptr, rc=rc) + dataptr(:) = soil_color_i(:) + call ESMF_FieldGet(field_o, farrayptr=dataptr, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + dataptr(:) = 0._r4 + + call ESMF_FieldRegrid(field_i, field_o, routehandle=routehandle, dynamicMask=dynamicMask, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + call ESMF_FieldGet(field_o, farrayptr=dataptr, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + do no = 1,ns_o + soil_color_o(no) = int(dataptr(no)) + if (soil_color_o(no) < 0 .or. soil_color_o(no) > nsoilcol) then + write (6,*) 'MKSOILCOL error: land model soil color = ', & + soil_color_o(no),' is not valid for lon,lat = ',no + call shr_sys_abort() + end if + end do + + ! Write output data + if (root_task) write(ndiag, '(a)') trim(subname)//" writing out soil color" + call mkfile_output(pioid_o, mesh_o, 'SOIL_COLOR', soil_color_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkfile_output') + if (root_task) write(ndiag, '(a)') trim(subname)//" writing out mksoil_color" + rcode = pio_inq_varid(pioid_o, 'mxsoil_color', pio_varid) + rcode = pio_put_var(pioid_o, pio_varid, nsoilcol) + call pio_syncfile(pioid_o) + + ! Compare global area of each soil color on input and output grids + call output_diagnostics_index(mesh_i, mesh_o, mask_i, frac_o, & + 0, nsoilcol, int(soil_color_i), soil_color_o, 'soil color type', ndiag, rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! Close the input file + call pio_closefile(pioid_i) + + ! Clean up memory + call ESMF_RouteHandleDestroy(routehandle, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + call ESMF_MeshDestroy(mesh_i, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + call ESMF_FieldDestroy(field_i, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + call ESMF_FieldDestroy(field_o, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + call ESMF_FieldDestroy(field_dstfrac, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + call ESMF_VMLogMemInfo("After destroy operations in "//trim(subname)) + + if (root_task) then + write (ndiag,'(a)') 'Successfully made soil color classes' + write (ndiag,'(a)') + end if + + end subroutine mksoilcol + + !================================================================================================ + subroutine get_dominant_soilcol(dynamicMaskList, dynamicSrcMaskValue, dynamicDstMaskValue, rc) + + ! input/output arguments + type(ESMF_DynamicMaskElementR4R8R4) , pointer :: dynamicMaskList(:) + real(ESMF_KIND_R4) , intent(in), optional :: dynamicSrcMaskValue + real(ESMF_KIND_R4) , intent(in), optional :: dynamicDstMaskValue + integer , intent(out) :: rc + + ! local variables + integer :: ni, no, n + real(ESMF_KIND_R4) :: wts_o(0:num_soilcolors) + logical :: has_color + integer :: soil_color_o + integer :: maxindex(1) + !--------------------------------------------------------------- + + rc = ESMF_SUCCESS + + if (associated(dynamicMaskList)) then + do no = 1, size(dynamicMaskList) + wts_o(:) = 0.d0 + do ni = 1, size(dynamicMaskList(no)%factor) + if (dynamicSrcMaskValue /= dynamicMaskList(no)%srcElement(ni)) then + do n = 0,num_soilcolors + if (dynamicMaskList(no)%srcElement(ni) == n) then + wts_o(n) = wts_o(n) + dynamicMaskList(no)%factor(ni) + end if + enddo + end if + end do + + ! If the output cell has any non-zero-colored inputs, then set the weight of + ! zero-colored inputs to 0, to ensure that the zero-color is NOT dominant. + soil_color_o = 0 + if (any(wts_o(1:num_soilcolors) > 0.)) then + has_color = .true. + wts_o(0) = 0.0 + else + has_color = .false. + end if + + ! Find index of maximum weight + if (has_color) then + call mkrank (num_soilcolors, wts_o(0:num_soilcolors), maxindex) + soil_color_o = maxindex(1) + end if + + ! If no color, set color to 15 (in older dataset generic soil color 4) + if (num_soilcolors == 8) then + if (soil_color_o == 0) then + soil_color_o = 4 + end if + else if (num_soilcolors == 20) then + if (soil_color_o == 0) then + soil_color_o = 15 + end if + end if + dynamicMaskList(no)%dstElement = real(soil_color_o, kind=r4) + + end do + end if + + contains + + subroutine mkrank (n, a, iv) + ! Return indices of largest [num] values in array [a]. + + ! input/output variables + integer , intent(in) :: n !array length + real(r4), intent(in) :: a(0:n) !array to be ranked + integer , intent(out):: iv(1) !index to [num] largest values in array [a] + + ! local variables: + real(r4) :: a_max !maximum value in array + real(r4) :: delmax !tolerance for finding if larger value + integer :: i !array index + integer :: m !do loop index + integer :: k !do loop index + integer :: miss !missing data value + !----------------------------------------------------------------------- + + ! Find index of largest non-zero number + delmax = 1.e-06 + miss = 9999 + iv(1) = miss + + a_max = -9999. + do i = 0, n + if (a(i)>0. .and. (a(i)-a_max)>delmax) then + a_max = a(i) + iv(1) = i + end if + end do + ! iv(1) = miss indicates no values > 0. this is an error + if (iv(1) == miss) then + write (6,*) 'MKRANK error: iv(1) = missing' + call shr_sys_abort() + end if + end subroutine mkrank + + end subroutine get_dominant_soilcol + +end module mksoilcolMod diff --git a/tools/mksurfdata_esmf/src/mksoildepthMod.F90 b/tools/mksurfdata_esmf/src/mksoildepthMod.F90 new file mode 100644 index 0000000000..9b7b44f709 --- /dev/null +++ b/tools/mksurfdata_esmf/src/mksoildepthMod.F90 @@ -0,0 +1,188 @@ +module mksoildepthMod + + !----------------------------------------------------------------------- + ! make fraction soildepth from input soildepth data + !----------------------------------------------------------------------- + ! + use ESMF + use pio , only : file_desc_t, pio_openfile, pio_closefile, pio_nowrite, pio_syncfile + use shr_kind_mod , only : r8 => shr_kind_r8, r4=>shr_kind_r4, cs => shr_kind_cs + use shr_sys_mod , only : shr_sys_abort + use mkpioMod , only : mkpio_get_rawdata + use mkpioMod , only : pio_iotype, pio_ioformat, pio_iosystem + use mkesmfMod , only : regrid_rawdata, create_routehandle_r8 + use mkdiagnosticsMod , only : output_diagnostics_area + use mkutilsMod , only : chkerr + use mkchecksMod , only : min_bad, max_bad + use mkfileMod , only : mkfile_output + use mkvarctl + + implicit none + private + + public mksoildepth ! regrid soildepth data + + character(len=*) , parameter :: u_FILE_u = & + __FILE__ + +!=============================================================== +contains +!=============================================================== + + subroutine mksoildepth(file_mesh_i, file_data_i, mesh_o, pioid_o, rc) + ! + ! make soildepth + ! + ! input/output variables + character(len=*) , intent(in) :: file_mesh_i ! input mesh file name + character(len=*) , intent(in) :: file_data_i ! input data file name + type(ESMF_Mesh) , intent(in) :: mesh_o ! output mesh + type(file_desc_t) , intent(inout) :: pioid_o + integer , intent(out) :: rc + + ! local variables: + type(ESMF_RouteHandle) :: routehandle + type(ESMF_Mesh) :: mesh_i + type(file_desc_t) :: pioid_i + integer :: ns_i, ns_o + integer :: ni, no + integer , allocatable :: mask_i(:) + real(r8), allocatable :: frac_i(:) + real(r8), allocatable :: frac_o(:) + real(r8), allocatable :: soildepth_i(:) + real(r8), allocatable :: soildepth_o(:) ! output grid: fraction soildepth + character(len=CS) :: varname + integer :: varnum + real(r8), parameter :: min_valid = 0._r8 ! minimum valid value + real(r8), parameter :: max_valid = 100.000001_r8 ! maximum valid value + integer :: ier, rcode ! error status + character(len=*), parameter :: subname = 'mksoildepth' + !----------------------------------------------------------------------- + + rc = ESMF_SUCCESS + + if (root_task) then + write (ndiag,'(a)') 'Attempting to make soildepth .....' + end if + + ! Open input data file + call ESMF_VMLogMemInfo("Before pio_openfile for "//trim(file_data_i)) + rcode = pio_openfile(pio_iosystem, pioid_i, pio_iotype, trim(file_data_i), pio_nowrite) + + ! Read in input mesh + call ESMF_VMLogMemInfo("Before create mesh_i in "//trim(subname)) + mesh_i = ESMF_MeshCreate(filename=trim(file_mesh_i), fileformat=ESMF_FILEFORMAT_ESMFMESH, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After create mesh_i in "//trim(subname)) + + ! Determine ns_i + call ESMF_MeshGet(mesh_i, numOwnedElements=ns_i, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Determine ns_o and allocate output data + call ESMF_MeshGet(mesh_o, numOwnedElements=ns_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + allocate ( soildepth_o(ns_o)); soildepth_o(:) = spval + + ! Get the landmask from the file and reset the mesh mask based on that + allocate(frac_o(ns_o),stat=ier) + if (ier/=0) call shr_sys_abort() + call create_routehandle_r8(mesh_i=mesh_i, mesh_o=mesh_o, norm_by_fracs=.true., & + routehandle=routehandle, frac_o=frac_o, rc=rc) + call ESMF_VMLogMemInfo("After create routehandle in "//trim(subname)) + allocate(frac_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort() + allocate(mask_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort() + call mkpio_get_rawdata(pioid_i, 'LANDMASK', mesh_i, frac_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + do ni = 1,ns_i + if (frac_i(ni) > 0._r4) then + mask_i(ni) = 1 + else + mask_i(ni) = 0 + end if + end do + call ESMF_MeshSet(mesh_i, elementMask=mask_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! Create a route handle between the input and output mesh and get frac_o + call create_routehandle_r8(mesh_i=mesh_i, mesh_o=mesh_o, norm_by_fracs=.true., & + routehandle=routehandle, frac_o=frac_o, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After create routehandle in "//trim(subname)) + do no = 1, ns_o + if ((frac_o(no) < 0.0) .or. (frac_o(no) > 1.0001)) then + write(6,*) "ERROR:: frac_o out of range: ", frac_o(no),no + call shr_sys_abort () + end if + end do + + ! Determine variable name to read in + varnum = 1 + select case (varnum) + case(1) + varname = 'Avg_Depth_Median' + case(2) + varname = 'Avg_Depth_Mean' + case(3) + varname = 'Upland_Valley_Depth_Median' + case(4) + varname = 'Upland_Valley_Depth_Mean' + case(5) + varname = 'Upland_Hillslope_Depth_Median' + case(6) + varname = 'Upland_Hillslope_Depth_Mean' + case(7) + varname = 'Lowland_Depth_Mean' + case(8) + varname = 'Lowland_Depth_Mean' + end select + + ! Read in input soil depth data + allocate(soildepth_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort() + call mkpio_get_rawdata(pioid_i, trim(varname), mesh_i, soildepth_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After mkpio_getrawdata in "//trim(subname)) + + ! Regrid soildepth_i to soildepth_o + call regrid_rawdata(mesh_i, mesh_o, routehandle, soildepth_i, soildepth_o, rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_LogWrite(subname//'after regrid rawdata in '//trim(subname)) + + ! Check validity of output data + if ( min_bad(soildepth_o, min_valid, 'soildepth') .or. & + max_bad(soildepth_o, max_valid, 'soildepth')) then + call shr_sys_abort() + end if + + ! Write output data + if (root_task) write(ndiag, '(a)') trim(subname)//" writing out soil depth" + call mkfile_output(pioid_o, mesh_o, 'zbedrock', soildepth_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkfile_output') + call pio_syncfile(pioid_o) + + ! Output diagnostic info + call output_diagnostics_area(mesh_i, mesh_o, mask_i, frac_o, & + soildepth_i, soildepth_o, "Soildepth", percent=.false., ndiag=ndiag, rc=rc) + + ! Close the input file + call pio_closefile(pioid_i) + call ESMF_VMLogMemInfo("After pio_closefile in "//trim(subname)) + + ! Release memory + call ESMF_RouteHandleDestroy(routehandle, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + call ESMF_MeshDestroy(mesh_i, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + call ESMF_VMLogMemInfo("After destroy operations in "//trim(subname)) + + if (root_task) then + write (ndiag,'(a)') 'Successfully made soildepth' + write (ndiag,*) + end if + + end subroutine mksoildepth + +end module mksoildepthMod diff --git a/tools/mksurfdata_esmf/src/mksoilfmaxMod.F90 b/tools/mksurfdata_esmf/src/mksoilfmaxMod.F90 new file mode 100644 index 0000000000..22cf159849 --- /dev/null +++ b/tools/mksurfdata_esmf/src/mksoilfmaxMod.F90 @@ -0,0 +1,170 @@ +module mksoilfmaxMod + + !----------------------------------------------------------------------- + ! Make soil fmax + !----------------------------------------------------------------------- + + use ESMF + use shr_kind_mod , only : r8 => shr_kind_r8, r4=>shr_kind_r4 + use shr_sys_mod , only : shr_sys_abort + use pio , only : file_desc_t, pio_openfile, pio_closefile, pio_nowrite, pio_syncfile + use mkpioMod , only : mkpio_get_rawdata, pio_iotype, pio_iosystem + use mkesmfMod , only : regrid_rawdata, create_routehandle_r8 + use mkdiagnosticsMod , only : output_diagnostics_area + use mkvarctl , only : ndiag, root_task, spval + use mkutilsMod , only : chkerr + use mkfileMod , only : mkfile_output + + implicit none + private ! By default make data private + + public :: mksoilfmax ! Make percent fmax + + character(len=*) , parameter :: u_FILE_u = & + __FILE__ + +!================================================================================= +contains +!================================================================================= + + subroutine mksoilfmax(file_mesh_i, file_data_i, mesh_o, pioid_o, rc) + ! + ! make percent fmax + ! + ! input/output variables + character(len=*) , intent(in) :: file_mesh_i ! input mesh file name + character(len=*) , intent(in) :: file_data_i ! input data file name + type(ESMF_Mesh) , intent(in) :: mesh_o ! output mesh + type(file_desc_t) , intent(inout) :: pioid_o + integer , intent(out) :: rc + + ! local variables: + type(ESMF_RouteHandle) :: routehandle + type(ESMF_Mesh) :: mesh_i + type(file_desc_t) :: pioid_i + integer :: ni,no + integer :: ns_i, ns_o + integer :: n,l,k + integer , allocatable :: mask_i(:) + real(r8), allocatable :: frac_i(:) + real(r8), allocatable :: frac_o(:) + real(r8), allocatable :: fmax_i(:) ! input grid: percent fmax + real(r8), allocatable :: fmax_o(:) ! output grid: %fmax + integer :: ier, rcode ! error status + character(len=32) :: subname = 'mksoilfmax' + !----------------------------------------------------------------------- + + rc = ESMF_SUCCESS + + if (root_task) then + write(ndiag,*) + write(ndiag,'(1x,80a1)') ('=',k=1,80) + write(ndiag,*) + write(ndiag,'(a)') 'Attempting to make %fmax .....' + write(ndiag,'(a)') ' Input file is '//trim(file_data_i) + write(ndiag,'(a)') ' Input mesh file is '//trim(file_mesh_i) + end if + call ESMF_VMLogMemInfo("At start of "//trim(subname)) + + ! Open input data file + rcode = pio_openfile(pio_iosystem, pioid_i, pio_iotype, trim(file_data_i), pio_nowrite) + + ! Read in input mesh + mesh_i = ESMF_MeshCreate(filename=trim(file_mesh_i), fileformat=ESMF_FILEFORMAT_ESMFMESH, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After create mesh_i in "//trim(subname)) + + ! Determine ns_i + call ESMF_MeshGet(mesh_i, numOwnedElements=ns_i, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Determine ns_o and allocate output data + call ESMF_MeshGet(mesh_o, numOwnedElements=ns_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + allocate(fmax_o(ns_o)); fmax_o(:) = spval + + ! Get the landmask from the file and reset the mesh mask based on that + allocate(frac_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort() + allocate(mask_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort() + call mkpio_get_rawdata(pioid_i, 'LANDMASK', mesh_i, frac_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + do ni = 1,ns_i + if (frac_i(ni) > 0._r8) then + mask_i(ni) = 1 + else + mask_i(ni) = 0 + end if + end do + call ESMF_MeshSet(mesh_i, elementMask=mask_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! Create a route handle between the input and output mesh + allocate(frac_o(ns_o)) + call create_routehandle_r8(mesh_i=mesh_i, mesh_o=mesh_o, norm_by_fracs=.true., & + routehandle=routehandle, frac_o=frac_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After create routehandle in "//trim(subname)) + do n = 1, ns_o + if ((frac_o(n) < 0.0) .or. (frac_o(n) > 1.0001)) then + write(6,*) "ERROR:: frac_o out of range: ", frac_o(n),n + end if + end do + + ! Read in input data + allocate(fmax_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort() + call mkpio_get_rawdata(pioid_i, 'FMAX', mesh_i, fmax_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After mkpio_getrawdata in "//trim(subname)) + + ! Regrid fmax_i to fmax_o, in points with no data, use globalAvg + fmax_i(:) = fmax_i(:) * frac_i(:) + fmax_o(:) = 0._r8 + call regrid_rawdata(mesh_i, mesh_o, routehandle, fmax_i, fmax_o, rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_LogWrite(subname//'after regrid rawdata in '//trim(subname)) + do n = 1,ns_o + if (frac_o(n) == 0._r8) then + fmax_o(n) = .365783_r8 + end if + end do + + ! Check for conservation + do no = 1, ns_o + if ((fmax_o(no)) > 1.000001_r8) then + write (6,*) 'MKFMAX error: fmax = ',fmax_o(no),' greater than 1.000001 for no = ',no + call shr_sys_abort() + end if + enddo + + ! Compare global areas on input and output grids + call output_diagnostics_area(mesh_i, mesh_o, mask_i, frac_o, & + fmax_i*0.01_r8, fmax_o*0.01_r8, "Max Fractional Sataturated Area", & + percent=.false., ndiag=ndiag, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Write output data + if (root_task) write(ndiag, '(a)') trim(subname)//" writing out soil fmax (maximum fraction saturated area)" + call mkfile_output (pioid_o, mesh_o, 'FMAX', fmax_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkfile_output') + call pio_syncfile(pioid_o) + + ! Close the input file + call pio_closefile(pioid_i) + + ! Release memory + call ESMF_RouteHandleDestroy(routehandle, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + call ESMF_MeshDestroy(mesh_i, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + + if (root_task) then + write (ndiag,'(a)') 'Successfully made %fmax' + end if + call ESMF_VMLogMemInfo("At end of "//trim(subname)) + + end subroutine mksoilfmax + +end module mksoilfmaxMod diff --git a/tools/mksurfdata_esmf/src/mksoiltexMod.F90 b/tools/mksurfdata_esmf/src/mksoiltexMod.F90 new file mode 100644 index 0000000000..fb8396f344 --- /dev/null +++ b/tools/mksurfdata_esmf/src/mksoiltexMod.F90 @@ -0,0 +1,614 @@ +module mksoiltexMod + + !----------------------------------------------------------------------- + ! Make soil data (texture) + !----------------------------------------------------------------------- + + use ESMF + use pio + use shr_kind_mod , only : r8 => shr_kind_r8, r4=>shr_kind_r4 + use shr_sys_mod , only : shr_sys_abort + use mkpioMod , only : mkpio_get_rawdata, mkpio_get_dimlengths + use mkpioMod , only : pio_iotype, pio_ioformat, pio_iosystem + use mkutilsMod , only : chkerr + use mkdiagnosticsMod , only : output_diagnostics_index + use mkfileMod , only : mkfile_output + use mkvarctl , only : root_task, ndiag, spval + use mkvarctl , only : unsetsoil + use mkvarpar , only : nlevsoi + + implicit none + private ! By default make data private + + public :: mksoiltex ! Set soil texture + + integer :: mapunit_value_max + integer :: num_soil_textures + type(ESMF_DynamicMask) :: dynamicMask + + character(len=*) , parameter :: u_FILE_u = & + __FILE__ + +!================================================================================= +contains +!================================================================================= + + subroutine mksoiltex(file_mesh_i, file_mapunit_i, file_lookup_i, mesh_o, pioid_o, rc) + ! + ! make %sand, %clay, organic carbon content, coarse fragments, bulk density, + ! and pH measured in H2O + ! + ! input/output variables + character(len=*) , intent(in) :: file_mesh_i ! input mesh/grid file name + character(len=*) , intent(in) :: file_mapunit_i ! input mapunit file name + character(len=*) , intent(in) :: file_lookup_i ! input data file name + type(ESMF_Mesh) , intent(in) :: mesh_o ! output mesh + type(file_desc_t) , intent(inout) :: pioid_o + integer , intent(out) :: rc + + ! local variables + type(ESMF_RouteHandle) :: routehandle + type(ESMF_Grid) :: grid_i + type(ESMF_Mesh) :: mesh_i + type(ESMF_Field) :: field_i + type(ESMF_Field) :: field_o + type(file_desc_t) :: pioid_i + type(var_desc_t) :: pio_varid + integer :: pio_vartype + integer :: dimid + integer :: ni,no + integer :: ns_i, ns_o + integer :: k,l,m,n + integer :: nlay ! number of soil layers + integer :: n_scid + integer , allocatable :: mask_i(:) + real(r4), pointer :: dataptr(:) + integer :: mapunit ! temporary igbp soil mapunit + integer, allocatable :: sand_i(:,:,:) ! input grid: percent sand + integer, allocatable :: clay_i(:,:,:) ! input grid: percent clay + integer, allocatable :: cfrag_i(:,:,:) ! input grid: coarse fragments (vol% > 2 mm) + real(r4), allocatable :: bulk_i(:,:,:) ! input grid: bulk density (g cm-3) + real(r4), allocatable :: orgc_i(:,:,:) ! input grid: organic carbon content (gC kg-1) + real(r4), allocatable :: phaq_i(:,:,:) ! input grid: soil pH measured in H2O (unitless) + real(r4), allocatable :: sand_o(:,:) ! output grid: % sand + real(r4), allocatable :: clay_o(:,:) ! output grid: % clay + real(r4), allocatable :: orgc_o(:,:) ! output grid: organic carbon content (gC kg-1) + real(r4), allocatable :: cfrag_o(:,:) ! output grid: coarse fragments (vol% > 2 mm) + real(r4), allocatable :: bulk_o(:,:) ! output grid: bulk density (g cm-3) + real(r4), allocatable :: phaq_o(:,:) ! output grid: soil pH measured in H2O (unitless) + real(r4), allocatable :: organic_o(:,:) ! output grid: organic matter (kg m-3) + integer :: n_mapunits + integer :: lookup_index + integer :: SCID + real(r4), allocatable :: mapunit_i(:) ! input grid: igbp soil mapunits + integer , allocatable :: mapunit_o(:) ! output grid: igbp soil mapunits + integer , allocatable :: MapUnits(:) + integer , allocatable :: mapunit_lookup(:) + type(var_desc_t) :: pio_varid_sand + type(var_desc_t) :: pio_varid_clay + type(var_desc_t) :: pio_varid_orgc + type(var_desc_t) :: pio_varid_cfrag + type(var_desc_t) :: pio_varid_bulk + type(var_desc_t) :: pio_varid_phaq + type(var_desc_t) :: pio_varid_organic + integer :: starts(3) ! starting indices for reading lookup table + integer :: counts(3) ! dimension counts for reading lookup table + integer :: srcTermProcessing_Value = 0 + integer :: rcode, ier ! error status + character(len=*), parameter :: subname = 'mksoiltex' + !----------------------------------------------------------------------- + + if (root_task) then + write(ndiag,*) + write(ndiag,'(1x,80a1)') ('=',k=1,80) + write(ndiag,*) + write(ndiag,'(a)') 'Attempting to make %sand, %clay, orgc, cfrag, bulk, phaq .....' + write(ndiag,'(a)') ' Input mapunit file is '//trim(file_mapunit_i) + write(ndiag,'(a)') ' Input lookup table file is '//trim(file_lookup_i) + write(ndiag,'(a)') ' Input mesh/grid file is '//trim(file_mesh_i) + end if + + ! Determine ns_o and allocate output data + call ESMF_MeshGet(mesh_o, numOwnedElements=ns_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + allocate(mapunit_o(ns_o)) ; mapunit_o(:) = 0 + allocate(sand_o(ns_o,nlevsoi)) ; sand_o(:,:) = spval + allocate(clay_o(ns_o,nlevsoi)) ; clay_o(:,:) = spval + allocate(orgc_o(ns_o,nlevsoi)) ; orgc_o(:,:) = spval + allocate(cfrag_o(ns_o,nlevsoi)) ; cfrag_o(:,:) = spval + allocate(bulk_o(ns_o,nlevsoi)) ; bulk_o(:,:) = spval + allocate(phaq_o(ns_o,nlevsoi)) ; phaq_o(:,:) = spval + allocate(organic_o(ns_o,nlevsoi)) ; organic_o(:,:) = spval + + !--------------------------------- + ! Determine mapunits on output grid + !--------------------------------- + + ! Determine input mesh + if (trim(file_mesh_i) == trim(file_mapunit_i)) then + ! input format is GRIDSPEC and read in grid and then create mesh + if (root_task) write(ndiag,*)"reading grid_i and then creating mesh_i in "//trim(subname) + call ESMF_VMLogMemInfo("Before create read in grid_i in "//trim(subname)) + grid_i = ESMF_GridCreate(filename=trim(file_mesh_i), & + fileformat=ESMF_FILEFORMAT_GRIDSPEC, addCornerStagger=.true., addmask=.true., varname='MU', rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("Before create mesh_i in "//trim(subname)) + mesh_i = esmf_meshcreate(grid_i, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After create mesh_i in "//trim(subname)) + else + ! Read in mesh directly + if (root_task) write(ndiag,*)"reading mesh_i directly in "//trim(subname) + mesh_i = ESMF_MeshCreate(filename=trim(file_mesh_i), fileformat=ESMF_FILEFORMAT_ESMFMESH, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + end if + + ! Determine ns_i (use the distgrid to the number of elements) + call ESMF_MeshGet(mesh_i, numOwnedElements=ns_i, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Read in mapunit data + if (root_task) write(ndiag,*)"Reading in mapunit data in "//trim(subname) + call ESMF_VMLogMemInfo("Before pio_openfile for "//trim(file_mapunit_i)) + rcode = pio_openfile(pio_iosystem, pioid_i, pio_iotype, trim(file_mapunit_i), pio_nowrite) + allocate(mapunit_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort() + call mkpio_get_rawdata(pioid_i, 'MU', mesh_i, mapunit_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After mkpio_getrawdata in "//trim(subname)) + call pio_closefile(pioid_i) + + ! Set mesh mask to zero where the mapunit values are 0 + if (root_task) write(ndiag,*)"Setting mask in mesh where mapunit data is 0 "//trim(subname) + allocate(mask_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort() + do ni = 1,ns_i + if (mapunit_i(ni) == 0.) then + mask_i(ni) = 0 + end if + end do + call ESMF_MeshSet(mesh_i, elementMask=mask_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! Create ESMF fields that will be used below + field_i = ESMF_FieldCreate(mesh_i, ESMF_TYPEKIND_R4, meshloc=ESMF_MESHLOC_ELEMENT, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + field_o = ESMF_FieldCreate(mesh_o, ESMF_TYPEKIND_R4, meshloc=ESMF_MESHLOC_ELEMENT, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! Create a route handle + if (root_task) write(ndiag,*)" before route handle creation "//trim(subname) + call ESMF_FieldRegridStore(field_i, field_o, routehandle=routehandle, & + regridmethod=ESMF_REGRIDMETHOD_CONSERVE, srcTermProcessing=srcTermProcessing_Value, & + ignoreDegenerate=.true., unmappedaction=ESMF_UNMAPPEDACTION_IGNORE, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After regridstore in "//trim(subname)) + if (root_task) write(ndiag,*)" after route handle creation "//trim(subname) + + ! Create a dynamic mask object + ! The dynamic mask object further holds a pointer to the routine that will be called in order to + ! handle dynamically masked elements - in this case its DynMaskProc (see below) + if (root_task) write(ndiag,*)" before call to dynamic mask set creation "//trim(subname) + call ESMF_DynamicMaskSetR4R8R4(dynamicMask, dynamicMaskRoutine=get_dominant_mapunit, & + handleAllElements=.true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + if (root_task) write(ndiag,*)" after call to dynamic mask set creation "//trim(subname) + + ! Determine values in field_i + call ESMF_FieldGet(field_i, farrayptr=dataptr, rc=rc) + dataptr(:) = real(mapunit_i(:), kind=r4) + + ! Determine mapunit_value_max (set it as a module variable so that it can be + ! accessible to gen_dominant_mapunit) - this is needed in the dynamic mask routine + mapunit_value_max = maxval(dataptr) + + ! Determine values in field_o + call ESMF_FieldGet(field_o, farrayptr=dataptr, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + dataptr(:) = 0._r4 + + ! Determine mapunit_o + call ESMF_FieldRegrid(field_i, field_o, routehandle=routehandle, dynamicMask=dynamicMask, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_FieldGet(field_o, farrayptr=dataptr, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + do no = 1,ns_o + mapunit_o(no) = int(dataptr(no)) + end do + + do no = 1,ns_o + if (mapunit_o(no) > mapunit_value_max) then + write(6,*)'mapunit_o is out of bounds ',mapunit_o(no) + ! call shr_sys_abort("mapunit_o is out of bounds") + end if + end do + + ! Write out mapunit_o + if (root_task) write(ndiag, '(a)') trim(subname)//" writing out mapunits " + call mkfile_output(pioid_o, mesh_o, 'mapunits', mapunit_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error calling mkfile_output for mapunits') + call pio_syncfile(pioid_o) + + !--------------------------------- + ! Determine %sand, %clay, orgc, cfrag, bulk, phaq on output grid using + ! mapunits + !--------------------------------- + if (root_task) then + write(ndiag,'(a)') 'WARNING: assigning sand_o = -4 to 99%' + write(ndiag,'(a)') 'WARNING: assigning other sand_o < 0 to 43%' + write(ndiag,'(a)') 'WARNING: assigning clay_o = -4 to 1%' + write(ndiag,'(a)') 'WARNING: assigning other clay_o < 0 to 18%' + write(ndiag,'(a)') 'WARNING: assigning orgc_o = -4 to 1' + write(ndiag,'(a)') 'WARNING: assigning other orgc_o < 0 to 0' +! write(ndiag,'(a)') 'WARNING: same warnings for organic_o as for orgc_o' + write(ndiag,'(a)') 'WARNING: same warnings for cfrag_o as for orgc_o' + write(ndiag,'(a)') 'WARNING: assigning bulk_o < 0 to 1.5' + write(ndiag,'(a)') 'WARNING: assigning phaq_o < 0 to 7' + end if + + rcode = pio_openfile(pio_iosystem, pioid_i, pio_iotype, trim(file_lookup_i), pio_nowrite) + + rcode = pio_inq_dimid (pioid_i, 'MapUnit', dimid) + rcode = pio_inq_dimlen (pioid_i, dimid, n_mapunits) + + rcode = pio_inq_dimid (pioid_i, 'soil_layer', dimid) + rcode = pio_inq_dimlen (pioid_i, dimid, nlay) + + rcode = pio_inq_dimid (pioid_i, 'SCID', dimid) + rcode = pio_inq_dimlen (pioid_i, dimid, n_scid) + + ! Read In MapUnits from the input file + allocate(MapUnits(n_mapunits), stat=ier) + if (ier/=0) call shr_sys_abort() + rcode = pio_inq_varid(pioid_i, 'MapUnit', pio_varid) + rcode = pio_get_var(pioid_i, pio_varid, MapUnits) + + ! Determine the mapunit lookup index from the value of the MapUnit variable + mapunit_value_max = maxval(MapUnits) + allocate(mapunit_lookup(mapunit_value_max)) + mapunit_lookup(:) = -999 + do n = 1,size(MapUnits) + mapunit_lookup(MapUnits(n)) = n + end do + + allocate(sand_i(nlay,n_scid,n_mapunits), stat=ier) + if (ier/=0) call shr_sys_abort() + allocate(clay_i(nlay,n_scid,n_mapunits), stat=ier) + if (ier/=0) call shr_sys_abort() + allocate(orgc_i(nlay,n_scid,n_mapunits), stat=ier) + if (ier/=0) call shr_sys_abort() + allocate(cfrag_i(nlay,n_scid,n_mapunits), stat=ier) + if (ier/=0) call shr_sys_abort() + allocate(bulk_i(nlay,n_scid,n_mapunits), stat=ier) + if (ier/=0) call shr_sys_abort() + allocate(phaq_i(nlay,n_scid,n_mapunits), stat=ier) + if (ier/=0) call shr_sys_abort() + + ! Get dimensions from input file and allocate memory for sand_i, clay_i, + ! organic carbon content, coarse fragments, bulk density, pH measured in H2O + rcode = pio_inq_varid(pioid_i, 'PCT_SAND', pio_varid_sand) + rcode = pio_inq_varid(pioid_i, 'PCT_CLAY', pio_varid_clay) + rcode = pio_inq_varid(pioid_i, 'ORGC', pio_varid_orgc) + rcode = pio_inq_varid(pioid_i, 'CFRAG', pio_varid_cfrag) + rcode = pio_inq_varid(pioid_i, 'BULK', pio_varid_bulk) + rcode = pio_inq_varid(pioid_i, 'PHAQ', pio_varid_phaq) + + rcode = pio_get_var(pioid_i, pio_varid_sand, sand_i) + rcode = pio_get_var(pioid_i, pio_varid_clay, clay_i) + rcode = pio_get_var(pioid_i, pio_varid_orgc, orgc_i) + rcode = pio_get_var(pioid_i, pio_varid_cfrag, cfrag_i) + rcode = pio_get_var(pioid_i, pio_varid_bulk, bulk_i) + rcode = pio_get_var(pioid_i, pio_varid_phaq, phaq_i) + + do no = 1,ns_o + + if (mapunit_o(no) == 0) then + + ! Set sand and clay to loam if mapunit is 0 + sand_o(no,:) = 43._r4 + clay_o(no,:) = 18._r4 + orgc_o(no,:) = 0._r4 + cfrag_o(no,:) = 0._r4 + bulk_o(no,:) = 1.5_r4 ! TODO Ok as a fill value? + phaq_o(no,:) = 7._r4 + organic_o(no,:) = 0._r4 + + else + + ! Determine lookup_index + lookup_index = mapunit_lookup(mapunit_o(no)) + + ! Determine top soil layer sand_o + ! If less than 0 search within the SCID array for the first index + ! that gives a value greater than or equal to 0 + ! Then determine the other soil layers + sand_o(no,1) = float(sand_i(1,1,lookup_index)) + if (sand_o(no,1) < 0._r4) then + do l = 2,n_scid + if (float(sand_i(1,l,lookup_index)) >= 0._r4) then + sand_o(no,1) = float(sand_i(1,l,lookup_index)) + exit + end if + end do + end if + if (sand_o(no,1) < 0._r4) then + if (int(sand_o(no,1)) == -4) then + sand_o(no,:) = 99._r4 + else + sand_o(no,:) = 43._r4 + end if + end if + do l = 2,nlay + sand_o(no,l) = float(sand_i(l,1,lookup_index)) + if (sand_o(no,l) < 0._r4) then + sand_o(no,l) = sand_o(no,l-1) + end if + end do + + ! Same algorithm for clay_o as for sand_o + clay_o(no,1) = float(clay_i(1,1,lookup_index)) + if (clay_o(no,1) < 0._r4) then + do l = 2,n_scid + if (float(clay_i(1,l,lookup_index)) >= 0._r4) then + clay_o(no,1) = float(clay_i(1,l,lookup_index)) + exit + end if + end do + end if + if (clay_o(no,1) < 0._r4) then + if (int(clay_o(no,1)) == -4) then + clay_o(no,:) = 1._r4 + else + clay_o(no,:) = 18._r4 + end if + end if + if (clay_o(no,1) < 0._r4) then + write(6,*)'ERROR: at no, lookup_index = ',no,lookup_index + call shr_sys_abort('could not find a value >= 0 for clay_i') + end if + do l = 2,nlay + clay_o(no,l) = float(clay_i(l,1,lookup_index)) + if (clay_o(no,l) < 0._r4) then + clay_o(no,l) = clay_o(no,l-1) + end if + end do + + ! Same algorithm for orgc_o as for sand_o + ! organic_o OPTION 2 (commented out) + ! Calculate from multiple input variables to get the output variable + orgc_o(no,1) = orgc_i(1,1,lookup_index) +! organic_o(no,1) = orgc_i(1,1,lookup_index) * bulk_i(1,1,lookup_index) * float(100 - cfrag_i(1,1,lookup_index)) * 0.01_r4 / 0.58_r4 + if (orgc_o(no,1) < 0._r4) then + do l = 2,n_scid + if (orgc_i(1,l,lookup_index) >= 0._r4) then + orgc_o(no,1) = orgc_i(1,l,lookup_index) +! organic_o(no,1) = orgc_i(1,l,lookup_index) * bulk_i(1,l,lookup_index) * float(100 - cfrag_i(1,l,lookup_index)) * 0.01_r4 / 0.58_r4 + exit + end if + end do + end if + if (orgc_o(no,1) < 0._r4) then + if (int(orgc_o(no,1)) == -4) then ! sand dunes + orgc_o(no,:) = 1._r4 +! organic_o(no,:) = 1._r4 + else + orgc_o(no,:) = 0._r4 +! organic_o(no,:) = 0._r4 + end if + end if + if (orgc_o(no,1) < 0._r4) then + write(6,*)'ERROR: at no, lookup_index = ',no,lookup_index + call shr_sys_abort('could not find a value >= 0 for orgc_i') + end if + do l = 2,nlay + orgc_o(no,l) = orgc_i(l,1,lookup_index) +! organic_o(no,l) = orgc_i(l,1,lookup_index) * bulk_i(l,1,lookup_index) * float(100 - cfrag_i(l,1,lookup_index)) * 0.01_r4 / 0.58_r4 + if (orgc_o(no,l) < 0._r4) then + orgc_o(no,l) = orgc_o(no,l-1) +! organic_o(no,l) = organic_o(no,l-1) + end if + end do + + ! Same algorithm for cfrag_o as for sand_o + cfrag_o(no,1) = float(cfrag_i(1,1,lookup_index)) + if (cfrag_o(no,1) < 0._r4) then + do l = 2,n_scid + if (float(cfrag_i(1,l,lookup_index)) >= 0._r4) then + cfrag_o(no,1) = float(cfrag_i(1,l,lookup_index)) + exit + end if + end do + end if + if (cfrag_o(no,1) < 0._r4) then + if (int(cfrag_o(no,1)) == -4) then ! sand dunes + cfrag_o(no,:) = 1._r4 + else + cfrag_o(no,:) = 0._r4 + end if + end if + if (cfrag_o(no,1) < 0._r4) then + write(6,*)'ERROR: at no, lookup_index = ',no,lookup_index + call shr_sys_abort('could not find a value >= 0 for cfrag_i') + end if + do l = 2,nlay + cfrag_o(no,l) = float(cfrag_i(l,1,lookup_index)) + if (cfrag_o(no,l) < 0._r4) then + cfrag_o(no,l) = cfrag_o(no,l-1) + end if + end do + + ! Same algorithm for bulk_o as for sand_o + bulk_o(no,1) = bulk_i(1,1,lookup_index) + if (bulk_o(no,1) < 0._r4) then + do l = 2,n_scid + if (bulk_i(1,l,lookup_index) >= 0._r4) then + bulk_o(no,1) = bulk_i(1,l,lookup_index) + exit + end if + end do + end if + if (bulk_o(no,1) < 0._r4) then + if (int(bulk_o(no,1)) == -4) then ! sand dunes + bulk_o(no,:) = 1.5_r4 ! TODO Ok for sand dunes? + else + bulk_o(no,:) = 1.5_r4 ! TODO Ok for -7? + end if + end if + if (bulk_o(no,1) < 0._r4) then + write(6,*)'ERROR: at no, lookup_index = ',no,lookup_index + call shr_sys_abort('could not find a value >= 0 for bulk_i') + end if + do l = 2,nlay + bulk_o(no,l) = bulk_i(l,1,lookup_index) + if (bulk_o(no,l) < 0._r4) then + bulk_o(no,l) = bulk_o(no,l-1) + end if + end do + + ! Same algorithm for phaq_o as for sand_o + phaq_o(no,1) = phaq_i(1,1,lookup_index) + if (phaq_o(no,1) < 0._r4) then + do l = 2,n_scid + if (phaq_i(1,l,lookup_index) >= 0._r4) then + phaq_o(no,1) = phaq_i(1,l,lookup_index) + exit + end if + end do + end if + if (phaq_o(no,1) < 0._r4) then + if (int(phaq_o(no,1)) == -4) then ! sand dunes + phaq_o(no,:) = 7._r4 + else + phaq_o(no,:) = 7._r4 + end if + end if + if (phaq_o(no,1) < 0._r4) then + write(6,*)'ERROR: at no, lookup_index = ',no,lookup_index + call shr_sys_abort('could not find a value >= 0 for phaq_i') + end if + do l = 2,nlay + phaq_o(no,l) = phaq_i(l,1,lookup_index) + if (phaq_o(no,l) < 0._r4) then + phaq_o(no,l) = phaq_o(no,l-1) + end if + end do + + ! --------------------------------------------------------------- + ! organic_o OPTION 1, as we plan to calculate organic in the CTSM + ! --------------------------------------------------------------- + ! Calculate organic from orgc_o, cfrag_o, and bulk_o, i.e. after + ! these terms have been regridded. The plan is to move this + ! calculation step from here to the CTSM. This approach keeps + ! ORGC the same in fsurdat as in the raw data. + ! Alternative approach considered but not selected: Regrid organic_i + ! (calculated from orgc_i, cfrag_i, and bulk_i) to organic_o. This + ! approach first calculates organic_i and then regrids to organic_o + ! rather than regridding all the terms first and then calculating + ! organic_o. Commented out code above belongs to that option. + do l = 1, nlay + organic_o(no,l) = orgc_o(no,l) * bulk_o(no,l) * & + (100._r4 - cfrag_o(no,l)) * 0.01_r4 / 0.58_r4 + end do + + end if + + end do + + if (root_task) write(ndiag, '(a)') trim(subname)//" writing out soil percent sand" + call mkfile_output(pioid_o, mesh_o, 'PCT_SAND', sand_o, lev1name='nlevsoi', rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error calling mkfile_output') + + if (root_task) write(ndiag, '(a)') trim(subname)//" writing out soil percent clay" + call mkfile_output(pioid_o, mesh_o, 'PCT_CLAY', clay_o, lev1name='nlevsoi', rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error calling mkfile_output') + + if (root_task) write(ndiag, '(a)') trim(subname)//" writing out soil organic matter" + call mkfile_output(pioid_o, mesh_o, 'ORGANIC', organic_o, lev1name='nlevsoi', rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error calling mkfile_output') + + if (root_task) write(ndiag, '(a)') trim(subname)//" writing out soil organic carbon content" + call mkfile_output(pioid_o, mesh_o, 'ORGC', orgc_o, lev1name='nlevsoi', rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error calling mkfile_output') + + if (root_task) write(ndiag, '(a)') trim(subname)//" writing out coarse fragments in soil" + call mkfile_output(pioid_o, mesh_o, 'CFRAG', cfrag_o, lev1name='nlevsoi', rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error calling mkfile_output') + + if (root_task) write(ndiag, '(a)') trim(subname)//" writing out soil bulk density" + call mkfile_output(pioid_o, mesh_o, 'BULK', bulk_o, lev1name='nlevsoi', rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error calling mkfile_output') + + if (root_task) write(ndiag, '(a)') trim(subname)//" writing out soil pH measured in H2O" + call mkfile_output(pioid_o, mesh_o, 'PHAQ', phaq_o, lev1name='nlevsoi', rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error calling mkfile_output') + + call pio_syncfile(pioid_o) + + ! Release memory + call ESMF_RouteHandleDestroy(routehandle, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + call ESMF_MeshDestroy(mesh_i, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + call ESMF_VMLogMemInfo("After destroy operations in "//trim(subname)) + + if (root_task) then + write(ndiag,'(a)') 'Successfully made %sand, %clay, orgc, cfrag, bulk, phaq .....' + end if + + end subroutine mksoiltex + + !================================================================================================ + subroutine get_dominant_mapunit(dynamicMaskList, dynamicSrcMaskValue, dynamicDstMaskValue, rc) + + use ESMF, only : ESMF_RC_ARG_BAD + + ! input/output arguments + type(ESMF_DynamicMaskElementR4R8R4) , pointer :: dynamicMaskList(:) + real(ESMF_KIND_R4) , intent(in), optional :: dynamicSrcMaskValue + real(ESMF_KIND_R4) , intent(in), optional :: dynamicDstMaskValue + integer , intent(out) :: rc + + ! local variables + integer :: ni, no, n + real(ESMF_KIND_R4) :: wts_o(0:mapunit_value_max) + integer :: maxindex(1) + real(ESMF_KIND_R4) :: maxvalue + character(len=*), parameter :: subname = 'mksoiltex' + !--------------------------------------------------------------- + + rc = ESMF_SUCCESS + + if (associated(dynamicMaskList)) then + do no = 1, size(dynamicMaskList) + dynamicMaskList(no)%dstElement = 0.d0 + wts_o(:) = 0.d0 + do ni = 1, size(dynamicMaskList(no)%factor) + if (dynamicMaskList(no)%srcElement(ni) > 0.d0) then + do n = 0,mapunit_value_max + if (dynamicMaskList(no)%srcElement(ni) == n) then + wts_o(n) = wts_o(n) + dynamicMaskList(no)%factor(ni) + end if + enddo + end if + end do + + ! Determine the most dominant index of wts_o + maxvalue = -999._r4 + maxindex = -999 + do n = 0,mapunit_value_max + if (wts_o(n) > maxvalue) then + maxindex(1) = n + maxvalue = wts_o(n) + end if + end do + if (maxindex(1) > mapunit_value_max) then + write(6,*)'mapunit_o is out of bounds ',maxindex(1) + call shr_sys_abort(subname//" mapunit_o is out of bounds") + end if + dynamicMaskList(no)%dstElement = real(maxindex(1), kind=r4) + end do + end if + + end subroutine get_dominant_mapunit + +end module mksoiltexMod diff --git a/tools/mksurfdata_esmf/src/mksurfdata.F90 b/tools/mksurfdata_esmf/src/mksurfdata.F90 new file mode 100644 index 0000000000..35ff1807cd --- /dev/null +++ b/tools/mksurfdata_esmf/src/mksurfdata.F90 @@ -0,0 +1,1495 @@ +program mksurfdata + + !----------------------------------------------------------------------- + ! mksurfdata creates land model surface dataset from original "raw" + ! data files. Surface dataset contains model grid, pfts, inland + ! water, glacier, soil texture, soil color, LAI and SAI, urban + ! fraction, and urban parameters. + ! ----------------------------------------------------------------------- + + ! ====================================================================== + ! Summary of input namelist + ! ====================================== + ! Must specify settings for the output grid: + ! ====================================== + ! mksrf_fgrid_mesh -- mesh for output grid + ! ====================================== + ! Must specify settings for input high resolution datafiles and corresponding meshes + ! ====================================== + ! mksrf_fglacier - Glacier dataset + ! mksrf_fglacier_mesh - Mesh for mksrf_fglacier + ! mksrf_fglacierregion - Glacier region ID dataset + ! mksrf_fglacierregion_mesh - Mesh for mksrf_fglacierregion + ! mksrf_flai - Leaf Area Index dataset + ! mksrf_flai_mesh - Mesh for mksrf_flai + ! mksrf_fpctlak - Percent lake dataset + ! mksrf_fpctlak_mesh - Mesh for mksrf_fpctlak + ! mksrf_flakdep - Lake depth dataset + ! mksrf_flakdep_mesh - Mesh for mksrf_flakdep + ! mksrf_fwetlnd - Wetland water dataset + ! mksrf_fwetlnd_mesh - Mesh for mksrf_fwetlnd + ! mksrf_fmax - Max fractional saturated area dataset + ! mksrf_fmax_mesh - Mesh for mksrf_fmax + ! mksrf_fsoicol - Soil color dataset + ! mksrf_fsoicol_mesh - Mesh for mksrf_fsoicol + ! mksrf_fsoitex - Soil texture dataset in mapunits + ! mksrf_fsoitex_lookup - Soil texture lookup for converting mapunits to sand/silt/clay and organic carbon content + ! mksrf_fsoitex_mesh - Mesh for mksrf_fsoitex + ! mksrf_furbtopo - Topography dataset (for limiting urban areas) + ! mksrf_furbtopo_mesh - Mesh for mksrf_furbtopo + ! mksrf_furban - Urban dataset + ! mksrf_furban_mesh - Mesh for mksrf_furban + ! mksrf_fvegtyp - PFT vegetation type dataset + ! mksrf_fpft_mesh - Mesh for mksrf_fvegtyp + ! mksrf_fhrvtyp - harvest type dataset + ! mksrf_fhrvtyp_mesh - Mesh for mksrf_flai harvesting + ! mksrf_fvocef - Volatile Organic Compund Emission Factor dataset + ! mksrf_fvocef_mesh - Mesh for mksrf_fvocef + ! mksrf_fgdp - GDP dataset + ! mksrf_fgdp_mesh - Mesh for mksrf_fgdp + ! mksrf_fpeat - Peatland dataset + ! mksrf_fpeat_mesh - Mesh for mksrf_fpeat + ! mksrf_fsoildepth - Soil depth dataset + ! mksrf_fsoildepth_mesh - Mesh for mksrf_fsoildepth + ! mksrf_fabm - Agricultural fire peak month dataset + ! mksrf_fabm_mesh - Mesh for mksrf_fabm + ! mksrf_ftopostats - Topography statistics dataset + ! mksrf_ftopostats_mesh - Mesh for mksrf_ftopostats + ! mksrf_ftopostats_override - Use this file to read in STD_ELEV and SLOPE + ! mksrf_fvic - VIC parameters dataset + ! mksrf_fvic_mesh - Mesh for mksrf_fvic + ! ====================================== + ! Optionally specify setting for: + ! ====================================== + ! mksrf_fdynuse ----- ASCII text file that lists each year of pft, urban, and lake files to use + ! mksrf_gridtype ---- Type of grid (default is 'global') + ! outnc_double ------ If output should be in double precision + ! outnc_large_files - If output should be in NetCDF large file format + ! outnc_vic --------- Output fields needed for VIC + ! outnc_3dglc ------- Output 3D glacier fields (normally only needed for comparasion) + ! nglcec ------------ If you want to change the number of Glacier elevation classes + ! gitdescribe ------- Description of this version from git + ! numpft ------------ Iif different than default of 16 + ! urban_skip_abort_on_invalid_data_check--- work around urban bug + ! no_inlandwet ------ If wetland should be set to 0% over land + ! ====================================== + ! Note: the folloiwng Optional settings have been REMOVED - + ! instead should now use tools subset_data and modify_fsurdat + ! ====================================== + ! all_veg ----------- If entire area is to be vegetated (pft_idx and pft_frc then required) + ! all_urban --------- If entire area is urban + ! soil_clay --------- If you want to change the soil_clay % to this value everywhere + ! soil_fmax --------- If you want to change the soil_fmax to this value everywhere + ! soil_sand --------- If you want to change the soil_sand % to this value everywhere + ! pft_idx ----------- If you want to change to 100% veg covered with given PFT indices + ! pft_frc ----------- Fractions that correspond to the pft_idx above + ! ====================================================================== + + use ESMF + use pio + use shr_kind_mod , only : r8 => shr_kind_r8, r4 => shr_kind_r4, cs => shr_kind_cs, cl => shr_kind_cl + use shr_sys_mod , only : shr_sys_abort + use mkVICparamsMod , only : mkVICparams + use mktopostatsMod , only : mktopostats + use mkpftMod , only : mkpft, mkpftInit + use mkpctPftTypeMod , only : pct_pft_type, get_pct_p2l_array, get_pct_l2g_array, update_max_array + use mkpftConstantsMod , only : natpft_lb, natpft_ub, cft_lb, cft_ub, num_cft, num_natpft + use mkdomainMod , only : mkdomain + use mkharvestMod , only : mkharvest + use mkgdpMod , only : mkgdp + use mkagfirepkmonthMod , only : mkagfirepkmon + use mklaiMod , only : mklai + use mkpeatMod , only : mkpeat + use mkvocefMod , only : mkvocef + use mkglcmecMod , only : mkglcmecInit, mkglcmec, mkglacier + use mkglacierregionMod , only : mkglacierregion + use mksoiltexMod , only : mksoiltex + use mksoilfmaxMod , only : mksoilfmax + use mksoildepthMod , only : mksoildepth + use mksoilcolMod , only : mksoilcol + use mkurbanparMod , only : mkurbanInit, mkurban, mkurbanpar, mkurban_topo, numurbl, update_max_array_urban + use mklanwatMod , only : mkpctlak, mklakdep, mkwetlnd, update_max_array_lake + use mkutilsMod , only : normalize_classes_by_gcell, chkerr + use mkfileMod , only : mkfile_define_dims, mkfile_define_atts, mkfile_define_vars + use mkfileMod , only : mkfile_output + use mkvarpar , only : nlevsoi, elev_thresh, numstdpft + use nanMod , only : nan, bigint + use mkpioMod , only : pio_iotype, pio_ioformat, pio_iosystem + use mkpioMod , only : mkpio_put_time_slice, mkpio_iodesc_output, mkpio_wopen + use mkinputMod + use mkvarctl + + implicit none + +#include + + ! indices + integer :: k,n ! indices + integer :: lsize_o ! Size of the local mesh elments + integer :: node_count ! Number of gridcells on the mesh + integer :: local_nodes(1) ! Local gridcells on the mesh + integer :: total_nodes(1) ! Total gridcells on the mesh + + ! error status + integer :: ier,rcode ! error status + + ! dynamic land use + integer :: nfdyn, nfpio ! unit numbers + integer :: ntim ! time sample for dynamic land use + integer :: year ! year for dynamic land use + integer :: year2 ! year for dynamic land use for harvest file + real(r8) :: suma ! local sum for error check + real(r8) :: loc_suma, glob_suma ! local and global sum for error check with mpi_allreduce + + ! model grid + real(r8), allocatable :: lon(:) + real(r8), allocatable :: lat(:) + + ! pct vegetation data + real(r8), allocatable :: landfrac_pft(:) ! PFT data: % land per gridcell + real(r8), allocatable :: pctlnd_pft(:) ! PFT data: % of gridcell for PFTs + type(pct_pft_type), allocatable :: pctnatpft(:) ! % of grid cell that is nat veg, and breakdown into PFTs + type(pct_pft_type), allocatable :: pctcft(:) ! % of grid cell that is crop, and breakdown into CFTs + + ! dynamic land use + real(r8) , allocatable :: pctlnd_pft_dyn(:) ! PFT data: % of gridcell for dyn landuse PFTs + type(pct_pft_type) , allocatable :: pctnatpft_max(:) ! % of grid cell maximum PFTs of the time series + type(pct_pft_type) , allocatable :: pctcft_max(:) ! % of grid cell maximum CFTs of the time series + real(r8) , allocatable :: pctnatveg(:) + real(r8) , allocatable :: pctcrop(:) + real(r8) , allocatable :: pct_nat_pft(:,:) + real(r8) , allocatable :: pct_cft(:,:) + logical :: end_of_fdynloop + + ! inland water data, glacier data and urban data + real(r8), allocatable :: pctlak(:) ! percent of grid cell that is lake + real(r8), allocatable :: pctlak_max(:) ! maximum percent of grid cell that is lake + real(r8), allocatable :: pctwet(:) ! percent of grid cell that is wetland + real(r8), allocatable :: pctocn(:) ! percent of grid cell that is ocean + real(r8), allocatable :: pctgla(:) ! percent of grid cell that is glacier + integer , allocatable :: urban_region(:) ! urban region ID + real(r8), allocatable :: pcturb(:) ! percent of grid cell that is urbanized (total across all urban classes) + real(r8), allocatable :: pcturb_max(:,:) ! maximum percent cover of each urban class, as % of grid cell + real(r8), allocatable :: urban_classes(:,:) ! percent cover of each urban class, as % of total urban area + real(r8), allocatable :: urban_classes_g(:,:) ! percent cover of each urban class, as % of grid cell + real(r8), allocatable :: elev(:) ! glc elevation (m) + real(r8), allocatable :: pctwet_orig(:) ! percent wetland of gridcell before dynamic land use adjustments + real(r8), allocatable :: pctgla_orig(:) ! percent glacier of gridcell before dynamic land use adjustments + + ! other variables written to file + real(r8), allocatable :: landfrac_mksurfdata(:) ! land fraction used for renormalization of areas + + ! pio/esmf variables + type(file_desc_t) :: pioid + type(var_desc_t) :: pio_varid + type(io_desc_t) :: pio_iodesc + integer :: petcount + integer :: stride + type(ESMF_Mesh) :: mesh_model + type(ESMF_Field) :: field_model + type(ESMF_LogKind_Flag) :: logkindflag + type(ESMF_VM) :: vm + integer :: rc + + ! character variables + character(len=CL) :: default_log_suffix ! default log file suffix to use for ESMF PET files + character(len=CL) :: string ! string read in + character(len=CL) :: fname + character(len=*), parameter :: subname = 'mksrfdata' ! program name + + character(len=*), parameter :: u_FILE_u = & + __FILE__ + + ! ====================================================================== + ! Initialize MPI get the rank and determine root task + ! ====================================================================== + + call MPI_init(rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + mpicom = mpi_comm_world + + ! Determine root task + call MPI_comm_rank(mpicom, iam, rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + root_task = (iam == 0) + call MPI_comm_size(mpicom, npes, rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + + + ! ====================================================================== + ! Read in namelist before initializing MPI or ESMF + ! ====================================================================== + call read_namelist_input() + + ! ====================================================================== + ! Initialize ESMF and get mpicom from ESMF + ! ====================================================================== + + if (create_esmf_pet_files) then + logkindflag = ESMF_LOGKIND_MULTI + else + logkindflag = ESMF_LOGKIND_MULTI_ON_ERROR + end if + default_log_suffix = trim(mksrf_grid_name) // '_ESMF_LogFile' + call ESMF_Initialize(mpiCommunicator=MPICOM, logkindflag=logkindflag, logappendflag=.false., & + defaultDefaultLogFilename=trim(default_log_suffix), ioUnitLBound=5001, ioUnitUBound=5101, vm=vm, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + call ESMF_VMGetGlobal(vm, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + call ESMF_VMGet(vm, mpicommunicator=mpicom, localPet=iam, petcount=petcount, & + ssiLocalPetCount=stride, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + call ESMF_LogSet(flush=.true.) + call ESMF_LogWrite("mksurfdata starting", ESMF_LOGMSG_INFO) + ! + ! open output ndiag file + ! + if (root_task) then + open (newunit=ndiag, file=trim(fsurlog), iostat=ier) + if (ier /= 0) then + call shr_sys_abort(' failed to open ndiag file '//trim(fsurlog)) + end if + write (ndiag,'(a)') 'Attempting to create surface boundary data .....' + write (ndiag,'(72a1)') ("-",n=1,60) + flush(ndiag) + else + ndiag = 6 + end if + ! + ! Finish handling of the namelist control variables + ! + ! Broadcast namelist to all pes + ! root_task is a module variable in mkvarctl + call bcast_namelist_input() + + ! Write out namelist input to ndiag + call check_namelist_input() + call write_namelist_input() + + ! Some checking + if (root_task) then + write(ndiag,'(2(a,I))') ' npes = ', npes, ' grid size = ', grid_size + flush(ndiag) + end if + if (petcount > grid_size ) then + call shr_sys_abort(' ERROR: number of tasks exceeds the size of the grid' ) + end if + + ! ====================================================================== + ! Initialize PIO + ! ====================================================================== + + ! the following returns pio_iosystem + call pio_init(iam, mpicom, max(1,petcount/stride), 0, stride, PIO_REARR_SUBSET, pio_iosystem) + + ! Open txt file + if (root_task) then + write(ndiag,*)' Opening file and reading pio_iotype from txt file with the same name' + flush(ndiag) + open (newunit=nfpio, file='pio_iotype.txt', status='old', & + form='formatted', action='read', iostat=ier) + if (ier /= 0) then + call shr_sys_abort(subname//" failed to open file pio_iotype.txt") + end if + read(nfpio,*) ! skip file header + read(nfpio, '(i)', iostat=ier) pio_iotype + if (ier /= 0) then + call shr_sys_abort(subname//" failed to read file pio_iotype.txt") + end if + end if + call mpi_bcast(pio_iotype, 1, MPI_INTEGER, 0, mpicom, ier) + + pio_ioformat = PIO_64BIT_DATA + + call ESMF_LogWrite("finished initializing PIO", ESMF_LOGMSG_INFO) + + if (fsurlog == ' ') then + call shr_sys_abort(' ERROR: must specify fsurlog in namelist') + end if + + ! ====================================================================== + ! Create fsurdat + ! ====================================================================== + + ! Read in model mesh to determine the number of local points + call ESMF_LogWrite("MESH creation (if this takes too long [more than an hour] and hangs, you may need more memory...)", ESMF_LOGMSG_INFO) + mesh_model = ESMF_MeshCreate(filename=trim(mksrf_fgrid_mesh), fileformat=ESMF_FILEFORMAT_ESMFMESH, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + + ! Get the number of local destination points on my processor (lsize_o) + call ESMF_MeshGet(mesh_model, numOwnedElements=lsize_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + local_nodes(1) = lsize_o + call ESMF_VMAllReduce(vm, local_nodes, total_nodes, count=1, reduceflag=ESMF_REDUCE_SUM, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + node_count = total_nodes(1) + if (node_count /= grid_size) then + if (root_task) then + write (ndiag,'(a, I, a, I)') ' node_count = ', node_count, ' grid_size = ', grid_size + flush(ndiag) + end if + call shr_sys_abort(' ERROR: size of input mesh file does not agree with expected size of nx*ny' ) + end if + ! Initialize urban dimensions (needed to initialize the dimensions in fsurdat) + call ESMF_LogWrite("mkurbanInit...") + call mkurbanInit(mksrf_furban) + + ! Initialize pft/cft dimensions (needed to initialize the dimensions in fsurdat) + call ESMF_LogWrite("mkpftInit...") + call mkpftInit( ) + + ! If fsurdat is blank, then we do not write a surface dataset - but we may still + ! write a dynamic landuse file. This is useful if we are creating many datasets at + ! once, and don't want duplicate surface datasets. + ! + ! TODO(wjs, 2016-01-26) Ideally, we would also avoid doing the processing of + ! variables that are just needed by the surface dataset (not by the dynamic landuse + ! file). However, this would require some analysis of the above code, to determine + ! which processing is needed (directly or indirectly) in order to create a dynamic + ! landuse file. + + ! Open fsurdat and write out variables + if (fsurdat == ' ') then + if (root_task) then + write (ndiag,'(a)') ' fsurdat is blank: skipping writing surface dataset' + end if + else + if (root_task)then + write(ndiag,*) + write(ndiag,'(1x,80a1)') ('=',k=1,80) + flush(ndiag) + end if + + call ESMF_LogWrite("mkfile...") + ! Open file + ! TODO: what about setting no fill values? + call mkpio_wopen(trim(fsurdat), clobber=.true., pioid=pioid) + + ! Define dimensions + call mkfile_define_dims(pioid, nx=mksrf_fgrid_mesh_nx, ny=mksrf_fgrid_mesh_ny, dynlanduse=.false.) + + ! Define global attributes + call mkfile_define_atts(pioid, dynlanduse = .false.) + + ! Define variables + call mkfile_define_vars(pioid, dynlanduse = .false.) + + ! End define model + rcode = pio_enddef(pioid) + end if + + ! NOTE: do not deallocate pctlak, pctwet, pctglacier and pcturban + + ! ----------------------------------- + ! Write out natpft, cft, and time + ! ----------------------------------- + if (fsurdat /= ' ') then + rcode = pio_inq_varid(pioid, 'natpft', pio_varid) + rcode = pio_put_var(pioid, pio_varid, (/(n,n=natpft_lb,natpft_ub)/)) + if (num_cft > 0) then + rcode = pio_inq_varid(pioid, 'cft', pio_varid) + rcode = pio_put_var(pioid, pio_varid, (/(n,n=cft_lb,cft_ub)/)) + end if + end if + + ! ----------------------------------- + ! Make lats/lons of model + ! ----------------------------------- + allocate (lon(lsize_o)) ; lon(:) = spval + allocate (lat(lsize_o)) ; lat(:) = spval + call mkdomain(mesh_model, lon_o=lon, lat_o=lat, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkdomain') + if (fsurdat /= ' ') then + if (root_task) write(ndiag, '(a)') trim(subname)//" writing out model grid" + if (root_task) write(ndiag, '(a)') trim(subname)//" writing out LONGXY" + if (root_task) flush(ndiag) + call mkfile_output(pioid, mesh_model, 'LONGXY', lon, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkfile_output for LONGXY') + if (root_task) write(ndiag, '(a)') trim(subname)//" writing out LATIXY" + if (root_task) flush(ndiag) + call mkfile_output(pioid, mesh_model, 'LATIXY', lat, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkfile_output for LATIXY') + call pio_syncfile(pioid) + end if + + if (root_task)then + write(ndiag,*)' Initialization is complete, going on to process types of input files' + flush(ndiag) + end if + + ! ----------------------------------- + ! Make LAI and SAI from 1/2 degree data and write to surface dataset + ! Write to netcdf file is done inside mklai routine + ! ----------------------------------- + if (fsurdat /= ' ') then + call mklai(mksrf_flai_mesh, mksrf_flai, mesh_model, pioid, rc=rc) + flush(ndiag) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mklai') + end if + + ! ----------------------------------- + ! Make PFTs [pctnatpft, pctcft] from dataset [fvegtyp] + ! Make landfrac_pft + ! ----------------------------------- + ! Determine fractional land from pft dataset + allocate(pctlnd_pft(lsize_o)); pctlnd_pft(:) = spval + allocate(pctnatpft(lsize_o)) ; + allocate(pctcft(lsize_o)) ; + allocate(landfrac_pft(lsize_o)) ; landfrac_pft(:) = spval + call mkpft( mksrf_fvegtyp_mesh, mksrf_fvegtyp, mesh_model, & + pctlnd_o=pctlnd_pft, pctnatpft_o=pctnatpft, pctcft_o=pctcft, rc=rc) + flush(ndiag) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkdomain') + + do n = 1,lsize_o + landfrac_pft(n) = pctlnd_pft(n)/100._r8 + end do + if (fsurdat /= ' ') then + if (root_task) write(ndiag, '(a)') trim(subname)//" writing land fraction from pft dataset" + if (root_task) flush(ndiag) + call mkfile_output(pioid, mesh_model, 'LANDFRAC_PFT', landfrac_pft, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkfile_output') + call pio_syncfile(pioid) + end if + + ! ----------------------------------- + ! Make constant harvesting data at model resolution + ! ----------------------------------- + ! Note that this call must come after call to mkpftInit - since num_cft is set there + ! Output data is written in mkharvest + if (fsurdat /= ' ') then + call mkharvest( mksrf_fhrvtyp_mesh, mksrf_fhrvtyp, mesh_model, pioid, & + rc=rc ) + flush(ndiag) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkharvest_init') + end if + + ! ----------------------------------- + ! Make inland water [pctlak, pctwet] + ! ----------------------------------- + ! LAKEDEPTH is written out in the subroutine + ! Need to keep pctlak and pctwet external for use below + allocate ( pctlak(lsize_o)) ; pctlak(:) = spval + allocate ( pctlak_max(lsize_o)) ; pctlak_max(:) = spval + call mkpctlak(mksrf_fpctlak_mesh, mksrf_fpctlak, mesh_model, pctlak, pioid, & + rc=rc) + flush(ndiag) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkpctlak') + call mklakdep(mksrf_flakdep_mesh, mksrf_flakdep, mesh_model, pioid, fsurdat, & + rc=rc) + flush(ndiag) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mklakdep') + + allocate ( pctwet(lsize_o)) ; pctwet(:) = spval + allocate ( pctwet_orig(lsize_o)) ; pctwet_orig(:) = spval + call mkwetlnd(mksrf_fwetlnd_mesh, mksrf_fwetlnd, mesh_model, pctwet, rc=rc) + flush(ndiag) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkwetlnd') + + ! Initialize pctocn to zero. + ! Until ctsm5.1 we set pctwet = 100 at ocean points rather than + ! setting a pctocn. Starting with ctsm5.2, we set pctocn = 100 at + ! ocean points in subroutine normalize_and_check_landuse. + ! No regridding required. + allocate ( pctocn(lsize_o)); pctocn(:) = 0._r8 + + ! ----------------------------------- + ! Make glacier fraction [pctgla] from [fglacier] dataset + ! ----------------------------------- + allocate (pctgla(lsize_o)) ; pctgla(:) = spval + allocate (pctgla_orig(lsize_o)) ; pctgla_orig(:) = spval + call mkglacier (mksrf_fglacier_mesh, mksrf_fglacier, mesh_model, glac_o=pctgla, rc=rc) + flush(ndiag) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkglacier') + + ! ----------------------------------- + ! Make glacier region ID [glacier_region] from [fglacierregion] dataset + ! ----------------------------------- + if (fsurdat /= ' ') then + ! GLACIER_REGION is written out in the subroutine + call mkglacierregion(mksrf_fglacierregion_mesh, mksrf_fglacierregion, mesh_model, pioid, rc) + flush(ndiag) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkglacierregion') + end if + + ! ----------------------------------- + ! Make soil texture and organic carbon content [pctsand, pctclay, organic] + ! ----------------------------------- + if (fsurdat /= ' ') then + call mksoiltex( mksrf_fsoitex_mesh, file_mapunit_i=mksrf_fsoitex, file_lookup_i=mksrf_fsoitex_lookup, & + mesh_o=mesh_model, pioid_o=pioid, rc=rc) + flush(ndiag) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mksoiltex') + end if + + ! ----------------------------------- + ! Make soil color classes [soicol] [fsoicol] + ! ----------------------------------- + if (fsurdat /= ' ') then + ! SOIL_COLOR and mxsoil_color is written out in the subroutine + call mksoilcol( mksrf_fsoicol, mksrf_fsoicol_mesh, mesh_model, pioid, rc) + flush(ndiag) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mksoilcol') + end if + + ! ----------------------------------- + ! Make soil fmax [fmaxsoil] + ! ----------------------------------- + if (fsurdat /= ' ') then + ! FMAX is written out in the subroutine + call mksoilfmax( mksrf_fmax_mesh, mksrf_fmax, mesh_model, pioid, rc) + flush(ndiag) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mksoilfmax') + end if + + ! ----------------------------------- + ! Make GDP data [gdp] from [gdp] + ! ----------------------------------- + if (fsurdat /= ' ') then + ! gdp is written out in the subroutine + call mkgdp (mksrf_fgdp_mesh, mksrf_fgdp, mesh_model, pioid, rc=rc) + flush(ndiag) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkdomain') + end if + + ! ----------------------------------- + ! Make peat data [fpeat] from [peatf] + ! ----------------------------------- + if (fsurdat /= ' ') then + call mkpeat (mksrf_fpeat_mesh, mksrf_fpeat, mesh_model, pioid, rc=rc) + flush(ndiag) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkpeat') + end if + + ! ----------------------------------- + ! Make soil depth data [soildepth] from [soildepthf] + ! ----------------------------------- + if (fsurdat /= ' ') then + call mksoildepth( mksrf_fsoildepth_mesh, mksrf_fsoildepth, mesh_model, pioid, rc) + flush(ndiag) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mksoildepth') + end if + + ! ----------------------------------- + ! Make agricultural fire peak month data [abm] from [abm] + ! ----------------------------------- + if (fsurdat /= ' ') then + call mkagfirepkmon (mksrf_fabm_mesh, mksrf_fabm, mesh_model, pioid, rc=rc) + flush(ndiag) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkagfirepkmon') + end if + + ! ----------------------------------- + ! Make urban fraction [pcturb] from [furban] dataset and + ! ----------------------------------- + allocate (pcturb(lsize_o)) ; pcturb(:) = spval + allocate (pcturb_max(lsize_o, numurbl)) ; pcturb_max(:,:) = spval + allocate (urban_classes(lsize_o,numurbl)) ; urban_classes(:,:) = spval + allocate (urban_region(lsize_o)) ; urban_region(:) = -999 + call mkurban(mksrf_furban_mesh, mksrf_furban, mesh_model, pcturb, & + urban_classes, urban_region, rc=rc) + flush(ndiag) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkurban') + if (fsurdat /= ' ') then + if (root_task) write(ndiag, '(a)') trim(subname)//" writing out urban region id" + if (root_task) flush(ndiag) + call mkfile_output(pioid, mesh_model, 'URBAN_REGION_ID', urban_region, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkfile_output') + call pio_syncfile(pioid) + end if + ! Note that final values of urban are not set and written out until further down + + ! Adjust pcturb + ! Make elevation [elev] from [ftopo, ffrac] dataset + ! Used only to screen pcturb, screen pcturb by elevation threshold from elev dataset + allocate(elev(lsize_o)) + elev(:) = spval + ! NOTE(wjs, 2016-01-15) This uses the 'TOPO_ICE' variable for historical reasons + ! (this same dataset used to be used for glacier-related purposes as well). + ! TODO(wjs, 2016-01-15) A better solution for this urban screening would probably + ! be to modify the raw urban data; in that case, I believe we could remove furbtopo. + call mkurban_topo ( mksrf_furbtopo_mesh, mksrf_furbtopo, mesh_model, varname='TOPO_ICE', elev_o=elev, rc=rc) + flush(ndiag) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkurban_topo') + where (elev > elev_thresh) + pcturb = 0._r8 + end where + + ! ----------------------------------- + ! Compute topography statistics [topo_stddev, slope] from [ftopostats] + ! ----------------------------------- + if (fsurdat /= ' ') then + call mktopostats ( mksrf_ftopostats_mesh, mksrf_ftopostats, mksrf_ftopostats_override, & + mesh_model, pioid, rc=rc) + flush(ndiag) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mktopostats') + end if + + ! ----------------------------------- + ! Compute VIC parameters + ! ----------------------------------- + if (fsurdat /= ' ') then + if (outnc_vic) then + call mkVICparams ( mksrf_fvic_mesh, mksrf_fvic, mesh_model, pioid, rc) + flush(ndiag) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkVICparams') + end if + end if + + ! ----------------------------------- + ! Make VOC emission factors for isoprene [ef1_btr,ef1_fet,ef1_fdt,ef1_shr,ef1_grs,ef1_crp] + ! ----------------------------------- + if (fsurdat /= ' ') then + call mkvocef ( mksrf_fvocef_mesh, mksrf_fvocef, mesh_model, pioid, lat, rc) + flush(ndiag) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkvocef') + end if + + ! ----------------------------------- + ! Save special land unit areas of surface dataset + ! ----------------------------------- + + pctwet_orig(:) = pctwet(:) + pctgla_orig(:) = pctgla(:) + + ! ----------------------------------- + ! Perform other normalizations + ! ----------------------------------- + + ! Normalize land use and make sure things add up to 100% as well as + ! checking that things are as they should be. + allocate(landfrac_mksurfdata(lsize_o)) + call normalize_and_check_landuse(lsize_o) + + ! Write out sum of PFT's + do k = natpft_lb,natpft_ub + loc_suma = 0._r8 + do n = 1,lsize_o + loc_suma = loc_suma + pctnatpft(n)%get_one_pct_p2g(k) + enddo + call mpi_reduce(loc_suma, glob_suma, 1, MPI_REAL8, MPI_SUM, 0, mpicom, ier) + if (root_task) then + write(ndiag,*) 'sum over domain of pft ',k,glob_suma + flush(ndiag) + end if + enddo + if (root_task) write(ndiag,*) + do k = cft_lb,cft_ub + loc_suma = 0._r8 + do n = 1,lsize_o + loc_suma = loc_suma + pctcft(n)%get_one_pct_p2g(k) + enddo + call mpi_reduce(loc_suma, glob_suma, 1, MPI_REAL8, MPI_SUM, 0, mpicom, ier) + if (root_task) then + write(ndiag,*) 'sum over domain of cft ',k,glob_suma + end if + enddo + if (root_task) write(ndiag,*) + if (root_task) flush(ndiag) + + ! Make final values of percent urban by class and compute urban parameters + ! This call needs to occur after all corrections are made to pcturb + allocate (urban_classes_g(lsize_o,numurbl)); urban_classes_g(:,:) = spval + call normalize_classes_by_gcell(urban_classes, pcturb, urban_classes_g) + if (root_task) write(ndiag, '(a)') trim(subname)//" writing out percnt urban" + if (root_task) flush(ndiag) + + ! Make Urban Parameters from raw input data and write to surface dataset + ! Write to netcdf file is done inside mkurbanpar routine + if (fsurdat /= ' ') then + call mkurbanpar(mksrf_furban, pioid, mesh_model, urban_region, urban_classes_g, & + urban_skip_abort_on_invalid_data_check) + flush(ndiag) + end if + + ! ----------------------------------- + ! Write out PCT_URBAN, PCT_GLACIER, PCT_LAKE and PCT_WETLAND and + ! PCT_NATVEG, PCT_NAT_PFT, PCT_CROP and PCT_CFT + ! ----------------------------------- + + allocate(pctnatveg(lsize_o)) + allocate(pctcrop(lsize_o)) + allocate(pct_nat_pft(lsize_o, 0:num_natpft)) + if (num_cft > 0) then + allocate(pct_cft(lsize_o, num_cft)) + end if + + if (fsurdat /= ' ') then + if (root_task) write(ndiag, '(a)') trim(subname)//" writing out PCT_URBAN" + if (root_task) flush(ndiag) + call mkfile_output(pioid, mesh_model, 'PCT_URBAN', urban_classes_g, lev1name='numurbl', rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkfile_output for PCT_URBAN') + + if (root_task) write(ndiag, '(a)') trim(subname)//" writing out PCT_GLACIER" + if (root_task) flush(ndiag) + call mkfile_output(pioid, mesh_model, 'PCT_GLACIER', pctgla, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in mkfile_output for pctgla') + + if (root_task) write(ndiag, '(a)') trim(subname)//" writing out PCT_LAKE" + if (root_task) flush(ndiag) + call mkfile_output(pioid, mesh_model, 'PCT_LAKE', pctlak, rc=rc) + if (root_task) flush(ndiag) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in mkfile_output for pctlak') + + if (root_task) write(ndiag, '(a)') trim(subname)//" writing out PCT_WETLAND" + if (root_task) flush(ndiag) + call mkfile_output(pioid, mesh_model, 'PCT_WETLAND', pctwet, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in in mkfile_output for pctwet') + + if (root_task) write(ndiag, '(a)') trim(subname)//" writing out PCT_OCEAN" + call mkfile_output(pioid, mesh_model, 'PCT_OCEAN', pctocn, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in in mkfile_output for pctocn') + + if (root_task) write(ndiag, '(a)') trim(subname)//" writing PCT_NATVEG" + if (root_task) flush(ndiag) + call get_pct_l2g_array(pctnatpft, pctnatveg) + call mkfile_output(pioid, mesh_model, 'PCT_NATVEG', pctnatveg, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkfile_output for PCT_NATVEG') + + if (root_task) write(ndiag, '(a)') trim(subname)//" writing PCT_CROP" + if (root_task) flush(ndiag) + call get_pct_l2g_array(pctcft, pctcrop) + call mkfile_output(pioid, mesh_model, 'PCT_CROP', pctcrop, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkfile_output for PCT_CROP') + + if (root_task) write(ndiag, '(a)') trim(subname)//" writing PCT_NAT_PFT" + if (root_task) flush(ndiag) + if (lsize_o /= 0) then + call get_pct_p2l_array(pctnatpft, ndim1=lsize_o, ndim2=num_natpft+1, pct_p2l=pct_nat_pft) + else + pct_nat_pft(:,:) = 0. + end if + call mkfile_output(pioid, mesh_model, 'PCT_NAT_PFT', pct_nat_pft, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkfile_output for PCT_NAT_PFT') + + if (num_cft > 0) then + if (root_task) write(ndiag, '(a)') trim(subname)//" writing PCT_CFT" + if (root_task) flush(ndiag) + if (lsize_o /= 0) then + call get_pct_p2l_array(pctcft, ndim1=lsize_o, ndim2=num_cft, pct_p2l=pct_cft) + else + pct_cft(:,:) = 0. + end if + call mkfile_output(pioid, mesh_model, 'PCT_CFT', pct_cft, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkfile_output for PCT_CFT') + end if + + if (root_task) write(ndiag, '(a)') trim(subname)//" writing LANDFRAC_MKSURFDATA" + if (root_task) flush(ndiag) + call mkfile_output(pioid, mesh_model, 'LANDFRAC_MKSURFDATA', landfrac_mksurfdata, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkfile_output for LANDFRAC_MKSURFDATA') + end if + + ! ---------------------------------------------------------------------- + ! Make glacier multiple elevation classes [pctglcmec,topoglcmec] from [fglacier] dataset + ! ---------------------------------------------------------------------- + ! This call needs to occur after pctgla has been adjusted for the final time + if (fsurdat /= ' ') then + call mkglcmecInit (pioid) + call mkglcmec(mksrf_fglacier_mesh, mksrf_fglacier, mesh_model, pioid, rc=rc) + flush(ndiag) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkglcmec') + end if + + ! ---------------------------------------------------------------------- + ! Close surface dataset + ! ---------------------------------------------------------------------- + if (fsurdat /= ' ') then + call pio_closefile(pioid) + if (root_task) then + write(ndiag,*) + write(ndiag,'(a)') 'Successfully created surface data output file = '//trim(fsurdat) + write(ndiag,'(a)') ' This file contains the land model surface data' + write(ndiag,*) + flush(ndiag) + end if + end if + + ! ====================================================================== + ! Create fdyndat if appropriate + ! ====================================================================== + +1000 continue + + if (mksrf_fdynuse /= ' ') then + + if (fdyndat == ' ') then + call shr_sys_abort(' must specify fdyndat in namelist if mksrf_fdynuse is not blank') + end if + + if (root_task) then + write(ndiag,*) + write(ndiag,'(1x,80a1)') ('=',k=1,80) + write(ndiag,'(1x,80a1)') ('*',k=1,80) + write(ndiag,'(1x,80a1)') ('=',k=1,80) + write(ndiag,*) + write(ndiag,'(a)')'Creating dynamic land use dataset '//trim(fdyndat) + flush(ndiag) + end if + + allocate(pctcft_max(lsize_o)) ; + allocate(pctnatpft_max(lsize_o)) ; + allocate(pctlnd_pft_dyn(lsize_o)) + + ! open output file + call mkpio_wopen(trim(fdyndat), clobber=.true., pioid=pioid) + + ! Define dimensions + call mkfile_define_dims(pioid, nx=mksrf_fgrid_mesh_nx, ny=mksrf_fgrid_mesh_ny, dynlanduse=.true.) + + ! Define global attributes + call mkfile_define_atts(pioid, dynlanduse = .true.) + + ! Define variables + call mkfile_define_vars(pioid, dynlanduse = .true.) + + ! End define mode + rcode = pio_enddef(pioid) + + ! Write out model grid + if (root_task) write(ndiag, '(a)') trim(subname)//" writing out LONGXY" + if (root_task) flush(ndiag) + call mkfile_output(pioid, mesh_model, 'LONGXY', lon, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkfile_output') + if (root_task) write(ndiag, '(a)') trim(subname)//" writing out LATIXY" + if (root_task) flush(ndiag) + call mkfile_output(pioid, mesh_model, 'LATIXY', lat, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkfile_output') + + ! Write out natpft + if (root_task) write(ndiag, '(a)') trim(subname)//" writing out natpft" + if (root_task) flush(ndiag) + rcode = pio_inq_varid(pioid, 'natpft', pio_varid) + rcode = pio_put_var(pioid, pio_varid, (/(n,n=natpft_lb,natpft_ub)/)) + + ! Write out cft + if (root_task) write(ndiag, '(a)') trim(subname)//" writing out cft" + if (root_task) flush(ndiag) + rcode = pio_inq_varid(pioid, 'cft', pio_varid) + rcode = pio_put_var(pioid, pio_varid, (/(n,n=cft_lb,cft_ub)/)) + + ! Write out LANDFRAC_PFT + ! landfrac_pft was calculated ABOVE + if (root_task) write(ndiag, '(a)') trim(subname)//" writing land fraction calculated in fsurdata calc)" + if (root_task) flush(ndiag) + call mkfile_output(pioid, mesh_model, 'LANDFRAC_PFT', landfrac_pft, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkfile_output for LANDFRAC_PFT') + + ! ----------------------------------------- + ! Read in each dynamic pft landuse dataset + ! ----------------------------------------- + + ! Open txt file + if (root_task) then + write(ndiag,'(a)')' Opening '//trim(mksrf_fdynuse)//' to read dynamic data forcing ' + flush(ndiag) + open (newunit=nfdyn, file=trim(mksrf_fdynuse), form='formatted', iostat=ier) + if (ier /= 0) then + call shr_sys_abort(subname//" failed to open file "//trim(mksrf_fdynuse)) + end if + end if + + pctnatpft_max = pctnatpft + pctcft_max = pctcft + pcturb_max = urban_classes_g + pctlak_max = pctlak + + end_of_fdynloop = .false. + ntim = 0 + do + + ! Determine file name - if there are no more files than exit before broadcasting + if (root_task) then + read(nfdyn, '(A195,1x,I4)', iostat=ier) string, year + if (ier /= 0) end_of_fdynloop = .true. + end if + call mpi_bcast(end_of_fdynloop, 1, MPI_LOGICAL, 0, mpicom, ier) + if (end_of_fdynloop) then + EXIT + end if + call mpi_bcast (string, len(string), MPI_CHARACTER, 0, mpicom, ier) + call mpi_bcast (year, 1, MPI_INTEGER, 0, mpicom, ier) + + ! Intrepret string as a filename with PFT and harvesting values in it + + fname = string + if (root_task) then + read(nfdyn, '(A195,1x,I4)', iostat=ier) fhrvname, year2 + write(ndiag,'(a,i8,a)')' input pft dynamic dataset for year ', year,' is : '//trim(fname) + flush(ndiag) + end if + call mpi_bcast (fhrvname, len(fhrvname), MPI_CHARACTER, 0, mpicom, ier) + call mpi_bcast (year2, 1, MPI_INTEGER, 0, mpicom, ier) + if ( year2 /= year ) then + if (root_task) then + write(ndiag,*) subname, ' error: year for harvest not equal to year for PFT files' + flush(ndiag) + end if + call shr_sys_abort() + end if + ! Read input urban data + if (root_task) then + read(nfdyn, '(A195,1x,I4)', iostat=ier) furbname, year2 + write(ndiag,*)'input urban dynamic dataset for year ', year2, ' is : ', trim(furbname) + flush(ndiag) + end if + call mpi_bcast (furbname, len(furbname), MPI_CHARACTER, 0, mpicom, ier) + call mpi_bcast (year2, 1, MPI_INTEGER, 0, mpicom, ier) + if ( year2 /= year ) then + if (root_task) then + write(ndiag,*) subname, ' error: year for urban not equal to year for PFT files' + flush(ndiag) + end if + call shr_sys_abort() + end if + ! Read input lake data + if (root_task) then + read(nfdyn, '(A195,1x,I4)', iostat=ier) flakname, year2 + write(ndiag,*)'input lake dynamic dataset for year ', year2, ' is : ', trim(flakname) + flush(ndiag) + end if + call mpi_bcast (flakname, len(flakname), MPI_CHARACTER, 0, mpicom, ier) + call mpi_bcast (year2, 1, MPI_INTEGER, 0, mpicom, ier) + if ( year2 /= year ) then + if (root_task) then + write(ndiag,*) subname, ' error: year for lake not equal to year for PFT files' + flush(ndiag) + end if + call shr_sys_abort() + end if + + ntim = ntim + 1 + if (root_task) then + write(ndiag,'(a,i8)')subname//' ntime = ',ntim + flush(ndiag) + end if + + rcode = pio_inq_varid(pioid, 'YEAR', pio_varid) + rcode = pio_put_var(pioid, pio_varid, (/ntim/), year) + rcode = pio_inq_varid(pioid, 'time', pio_varid) + rcode = pio_put_var(pioid, pio_varid, (/ntim/), year) + !rcode = pio_inq_varid(pioid, 'input_pftdata_filename', pio_varid) + !rcode = pio_put_var(pioid, pio_varid, (/1,ntim/), (/len_trim(string),1/), trim(string)) + call pio_syncfile(pioid) + + ! Create pctpft data at model resolution from file fname + ! Note that pctlnd_o below is different than the above call and returns pctlnd_pft_dyn + call mkpft( mksrf_fvegtyp_mesh, fname, mesh_model, & + pctlnd_o=pctlnd_pft_dyn, pctnatpft_o=pctnatpft, pctcft_o=pctcft, & + rc=rc) + flush(ndiag) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkpft') + call pio_syncfile(pioid) + + ! Consistency check on input land fraction + ! pctlnd_pft was calculated ABOVE + do n = 1,lsize_o + if (pctlnd_pft_dyn(n) /= pctlnd_pft(n)) then + write(ndiag,*) subname,' error: pctlnd_pft for dynamics data = ',& + pctlnd_pft_dyn(n), ' not equal to pctlnd_pft for surface data = ',& + pctlnd_pft(n),' at n= ',n + if ( trim(fname) == ' ' )then + write(ndiag,*) ' PFT string = ',trim(string) + else + write(ndiag,*) ' PFT file = ', fname + end if + flush(ndiag) + call shr_sys_abort() + end if + end do + + ! Create harvesting data at model resolution + ! Output data is written in mkharvest + call mkharvest( mksrf_fhrvtyp_mesh, fhrvname, mesh_model, pioid, & + ntime=ntim, rc=rc ) + flush(ndiag) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkharvest') + call pio_syncfile(pioid) + + ! Create pctlak data at model resolution (use original mapping file from lake data) + call mkpctlak(mksrf_fpctlak_mesh, flakname, mesh_model, pctlak, pioid, & + rc=rc) + flush(ndiag) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkpctlak') + call pio_syncfile(pioid) + + call mkurban(mksrf_furban_mesh, furbname, mesh_model, pcturb, & + urban_classes, urban_region, rc=rc) + flush(ndiag) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkurban') + call pio_syncfile(pioid) + ! screen pcturb using elevation + where (elev > elev_thresh) + pcturb = 0._r8 + end where + + ! For landunits NOT read each year: reset to their pre-adjustment values + ! in preparation for redoing landunit area normalization + pctwet(:) = pctwet_orig(:) + pctgla(:) = pctgla_orig(:) + + ! Normalize land use and make sure things add up to 100% as well as + ! checking that things are as they should be. + if (root_task) then + write(ndiag,*) + write(ndiag,'(1x,80a1)') ('=',k=1,80) + write(ndiag,'(a)')' calling normalize_and_check_landuse' + flush(ndiag) + end if + call normalize_and_check_landuse(lsize_o) + call normalize_classes_by_gcell(urban_classes, pcturb, urban_classes_g) + + ! Given an array of pct_pft_type variables, update all the max_p2l variables. + call update_max_array(pctnatpft_max, pctnatpft) + call update_max_array(pctcft_max, pctcft) + call update_max_array_urban(pcturb_max,urban_classes_g) + call update_max_array_lake(pctlak_max,pctlak) + + if (root_task) write(ndiag, '(a,i8)') trim(subname)//" writing PCT_NAT_PFT for year ",year + if (root_task) flush(ndiag) + rcode = pio_inq_varid(pioid, 'PCT_NAT_PFT', pio_varid) + call pio_setframe(pioid, pio_varid, int(ntim, kind=Pio_Offset_Kind)) + call get_pct_p2l_array(pctnatpft, ndim1=lsize_o, ndim2=num_natpft+1, pct_p2l=pct_nat_pft) + call mkfile_output(pioid, mesh_model, 'PCT_NAT_PFT', pct_nat_pft, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkfile_output for PCT_NAT_PFT') + call pio_syncfile(pioid) + + if (root_task) write(ndiag, '(a,i8)') trim(subname)//" writing PCT_CROP for year ",year + if (root_task) flush(ndiag) + rcode = pio_inq_varid(pioid, 'PCT_CROP', pio_varid) + call pio_setframe(pioid, pio_varid, int(ntim, kind=Pio_Offset_Kind)) + call get_pct_l2g_array(pctcft, pctcrop) + call mkfile_output(pioid, mesh_model, 'PCT_CROP', pctcrop, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkfile_output for PCT_CROP') + call pio_syncfile(pioid) + + if (root_task) write(ndiag, '(a,i8)') trim(subname)//" writing PCT_URBAN for year ",year + if (root_task) flush(ndiag) + rcode = pio_inq_varid(pioid, 'PCT_URBAN', pio_varid) + call pio_setframe(pioid, pio_varid, int(ntim, kind=Pio_Offset_Kind)) + call mkfile_output(pioid, mesh_model, 'PCT_URBAN', urban_classes_g, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkfile_output for PCT_URBAN') + call pio_syncfile(pioid) + + if (root_task) write(ndiag, '(a,i8)') trim(subname)//" writing PCT_LAKE for year ",year + if (root_task) flush(ndiag) + rcode = pio_inq_varid(pioid, 'PCT_LAKE', pio_varid) + call pio_setframe(pioid, pio_varid, int(ntim, kind=Pio_Offset_Kind)) + call mkfile_output(pioid, mesh_model, 'PCT_LAKE', pctlak, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkfile_output for PCT_LAKE') + call pio_syncfile(pioid) + + if (num_cft > 0) then + if (root_task) write(ndiag, '(a,i8)') trim(subname)//" writing PCT_CFT for year ",year + if (root_task) flush(ndiag) + rcode = pio_inq_varid(pioid, 'PCT_CFT', pio_varid) + call pio_setframe(pioid, pio_varid, int(ntim, kind=Pio_Offset_Kind)) + call get_pct_p2l_array(pctcft, ndim1=lsize_o, ndim2=num_cft, pct_p2l=pct_cft) + call mkfile_output(pioid, mesh_model, 'PCT_CFT', pct_cft, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkfile_output for PCT_CFT') + call pio_syncfile(pioid) + end if + + if (root_task) write(ndiag, '(a,i8)') trim(subname)//" writing LANDFRAC_MKSURFDATA for year ",year + if (root_task) flush(ndiag) + rcode = pio_inq_varid(pioid, 'LANDFRAC_MKSURFDATA', pio_varid) + call pio_setframe(pioid, pio_varid, int(ntim, kind=Pio_Offset_Kind)) + call mkfile_output(pioid, mesh_model, 'LANDFRAC_MKSURFDATA', landfrac_mksurfdata, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkfile_output for LANDFRAC_MKSURFDATA') + call pio_syncfile(pioid) + + if (root_task) then + write(ndiag,'(1x,80a1)') ('=',k=1,80) + write(ndiag,*) + flush(ndiag) + end if + + end do ! end of read loop + + if (root_task) write(ndiag, '(a,i8)') trim(subname)//" writing PCT_NAT_PFT_MAX " + if (root_task) flush(ndiag) + call get_pct_p2l_array(pctnatpft_max, ndim1=lsize_o, ndim2=num_natpft+1, pct_p2l=pct_nat_pft) + call mkfile_output(pioid, mesh_model, 'PCT_NAT_PFT_MAX', pct_nat_pft, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkfile_output for PCT_NAT_PFT') + + if (root_task) write(ndiag, '(a,i8)') trim(subname)//" writing PCT_CROP_MAX" + if (root_task) flush(ndiag) + call get_pct_l2g_array(pctcft_max, pctcrop) + call mkfile_output(pioid, mesh_model, 'PCT_CROP_MAX', pctcrop, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkfile_output for PCT_CROP_MAX') + + if (root_task) write(ndiag, '(a,i8)') trim(subname)//" writing PCT_URBAN_MAX" + if (root_task) flush(ndiag) + call mkfile_output(pioid, mesh_model, 'PCT_URBAN_MAX', pcturb_max, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkfile_output for PCT_URBAN_MAX') + + if (root_task) write(ndiag, '(a,i8)') trim(subname)//" writing PCT_LAKE_MAX" + if (root_task) flush(ndiag) + call mkfile_output(pioid, mesh_model, 'PCT_LAKE_MAX', pctlak_max, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkfile_output for PCT_LAKE_MAX') + + if (num_cft > 0) then + if (root_task) write(ndiag, '(a,i8)') trim(subname)//" writing PCT_CFT_MAX" + if (root_task) flush(ndiag) + call get_pct_p2l_array(pctcft_max, ndim1=lsize_o, ndim2=num_cft, pct_p2l=pct_cft) + call mkfile_output(pioid, mesh_model, 'PCT_CFT_MAX', pct_cft, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkfile_output for PCT_CFT') + end if + + ! Close the file + call pio_closefile(pioid) + if (root_task) then + write(ndiag,*) + write(ndiag,'(a)') 'Successfully created landuse timeseries data output file = '//trim(fdyndat) + write(ndiag,'(a)') ' This file contains the land model time series data' + write(ndiag,*) + flush(ndiag) + end if + + end if ! end of if-create dynamic landust dataset + + ! ----------------------------------- + ! Wrap things up + ! ----------------------------------- + if (root_task) then + write(ndiag,'(a)') 'Successfully ran mksurfdata_esmf' + close (ndiag) + end if + + call ESMF_Finalize() + + !----------------------------------------------------------------------- + contains + !----------------------------------------------------------------------- + + subroutine normalize_and_check_landuse(ns_o) + ! + ! Normalize land use and make sure things add up to 100% as well as + ! checking that things are as they should be. + ! + ! Coming into this subroutine, landunit areas are expressed as percent of the + ! gridcell and are NOT normalized to sum to 100%. Coming out of this subroutine, + ! landunit areas are expressed as percent of the land portion of the gridcell and + ! ARE normalized to sum to 100%. + ! + ! input/output variables: + integer, intent(in) :: ns_o + + ! local variables: + integer :: k,n ! indices + integer :: nsmall ! number of small PFT values for a single check + integer :: nsmall_tot ! total number of small PFT values in all grid cells + real(r8) :: suma ! sum for error check + real(r8) :: pct_land ! area considered to be land (% of grid cell) + real(r8) :: frac_land ! area considered to be land (fraction of grid cell) + real(r8) :: new_total_natveg_pct ! new % veg (% of grid cell, natural veg) + real(r8), parameter :: tol_loose = 1.e-4_r8 ! tolerance for some 'loose' error checks + real(r8), parameter :: toosmallPFT = 1.e-10_r8 ! tolerance for PFT's to ignore + character(len=32) :: subname = 'normalize_and_check_landuse' ! subroutine name + !----------------------------------------------------------------------- + + do n = 1,ns_o + + ! Truncate all percentage fields on output grid. This is needed to + ! ensure that wt is zero (not a very small number such as + ! 1e-16) where it really should be zero + pctlak(n) = float(nint(pctlak(n))) + pctwet(n) = float(nint(pctwet(n))) + pctgla(n) = float(nint(pctgla(n))) + + ! Check preconditions + if ( pctlak(n) < 0.0_r8 )then + write(ndiag,*) subname, ' ERROR: pctlak is negative!' + write(ndiag,*) 'n, pctlak = ', n, pctlak(n) + flush(ndiag) + call shr_sys_abort() + end if + if ( pctwet(n) < 0.0_r8 )then + write(ndiag,*) subname, ' ERROR: pctwet is negative!' + write(ndiag,*) 'n, pctwet = ', n, pctwet(n) + flush(ndiag) + call shr_sys_abort() + end if + if ( pcturb(n) < 0.0_r8 )then + write(ndiag,*) subname, ' ERROR: pcturb is negative!' + write(ndiag,*) 'n, pcturb = ', n, pcturb(n) + flush(ndiag) + call shr_sys_abort() + end if + if ( pctgla(n) < 0.0_r8 )then + write(ndiag,*) subname, ' ERROR: pctgla is negative!' + write(ndiag,*) 'n, pctgla = ', n, pctgla(n) + flush(ndiag) + call shr_sys_abort() + end if + if ( pctcft(n)%get_pct_l2g() < 0.0_r8 )then + write(ndiag,*) subname, ' ERROR: pctcrop is negative!' + write(ndiag,*) 'n, pctcrop = ', n, pctcft(n)%get_pct_l2g() + flush(ndiag) + call shr_sys_abort() + end if + + ! Make sure sum of all land cover types except natural vegetation does + ! not exceed 100. If it does, subtract excess from these land cover + ! types proportionally. + suma = pctlak(n) + pctwet(n) + pcturb(n) + pctgla(n) + pctcft(n)%get_pct_l2g() + if (suma > 100._r4) then + pctlak(n) = pctlak(n) * 100._r8/suma + pctwet(n) = pctwet(n) * 100._r8/suma + pcturb(n) = pcturb(n) * 100._r8/suma + pctgla(n) = pctgla(n) * 100._r8/suma + call pctcft(n)%set_pct_l2g(pctcft(n)%get_pct_l2g() * 100._r8/suma) + end if + + suma = pctlak(n) + pctwet(n) + pcturb(n) + pctgla(n) + pctcft(n)%get_pct_l2g() + if (suma > (100._r8 + tol_loose)) then + write(ndiag,*) subname, ' ERROR: pctlak + pctwet + pcturb + pctgla + pctcrop must be' + write(ndiag,*) '<= 100% before normalizing natural vegetation area' + write(ndiag,*) 'n, pctlak, pctwet, pcturb, pctgla, pctcrop = ', & + n, pctlak(n), pctwet(n), pcturb(n), pctgla(n), pctcft(n)%get_pct_l2g() + flush(ndiag) + call shr_sys_abort() + end if + + ! Determine the percent of each grid cell considered to be land. (See comments in + ! https://github.com/ESCOMP/CTSM/issues/1716 for details.) + ! + ! Start by using the land fraction field from the PFT raw data set: + pct_land = pctlnd_pft(n) + ! + ! Brief summary of the following: But we don't want to overwrite special + ! landunits or crop with ocean where these special landunits extend beyond the + ! PFT data's land fraction. + ! + ! More details: + ! + ! In essence, this is saying that we'll let special landunit area grow into the + ! natveg area before growing into ocean, but we'll have special landunit area + ! grow into ocean before growing into crop or any other special landunit area. + ! (This check of special landunit area is particularly important for glaciers, + ! where we can have floating ice shelves, so we can have a scenario where + ! pctlnd_pft is 0 but we have non-zero glacier cover and we want the final grid + ! cell to be glacier-covered.) (We could possibly do better by considering the + ! land mask from each special landunit raw dataset, and even better by mapping + ! these various notions of land mask onto each other, but that starts to get + ! messy, and relies on the trustworthiness of each raw dataset's land mask... + ! this formulation seems reasonable enough.) + ! + ! Note that we include pct_crop in the following, but NOT pct_natveg. The + ! assumption behind that is that pct_crop is more reliable and/or more important, + ! and should not be overwritten, whereas pct_natveg can be overwritten with a + ! special landunit. For example, consider a case where the PFT dataset specifies + ! 40% land, with 20% crop and 10% natveg (so, implicitly, 10% special landunits). + ! If the only special landunit is glacier and it has 15% cover, then we want to + ! end up with the glacier overwriting natural veg, so we end up with 20% crop, 5% + ! natveg, 15% glacier and 60% ocean. However, if glacier has 30% cover, then we + ! will assume that some of that glacier extends over the ocean rather than + ! overwriting crop, so we end up with 20% crop, 30% glacier, 50% ocean and 0% + ! natveg. + ! + ! Another reason for excluding pct_natveg from the following is more pragmatic: + ! Typically, we expect the initial sum of all landunit areas to approximately + ! equal pctlnd_pft. This means that, in a coastal grid cell, if we included all + ! landunit areas in the following sum, then in many cases we would take the + ! final pct_land from the landunit sum rather than from pctlnd_pft. But in this + ! scenario where we take pct_land from the landunit sum, it is likely that + ! pct_land will vary from year to year on the landuse timeseries file. This + ! variation from year to year will cause a renormalization of all landunits, + ! leading to changes in the areas of landunits that should really stay fixed + ! from one year to the next. By excluding pct_natveg we give more wiggle room: + ! it will usually be the case that we take the final pct_land from pctlnd_pft, + ! which stays fixed in time, so that the renormalization stays the same from one + ! year to the next. The possible downside is that pct_natveg may end up varying + ! more than is ideal, but this seems better than letting all of the other + ! landunits vary when they should stay fixed. + ! + ! Also, note that this landunit sum agrees with the suma sums elsewhere; this + ! agreement may be important in some cases (so that if we changed the set of + ! landunits included in the sum here, some other changes may be needed below.) + pct_land = max(pct_land, suma) + ! + ! Make sure that we're not ending up with > 100% land area. This can arise if the + ! sum of special landunits exceeds 100% by roundoff; also, due to rounding + ! errors, pctlnd_pft may slightly differ from 100% when it should really be + ! exactly 100%; we want pct_land to be exactly 100% in this case: + if (pct_land > (100._r8 - 1.e-4_r8)) then + pct_land = 100._r8 + end if + + if (pct_land < 1.e-6_r8) then + ! If we have essentially 0 land area, set land area to exactly 0 and put all + ! area in pctocn. Note that, based on the formulation + ! for pct_land above, this should only arise if the non-natveg landunits + ! already have near-zero area (and the natveg landunit should also have + ! near-zero area in this case, because its area should be no greater than the + ! land fraction from the PFT raw dataset), so the zeroing of these other + ! landunits should only result in changes near the roundoff level. + pct_land = 0._r8 + frac_land = 0._r8 + call pctnatpft(n)%set_pct_l2g(0._r8) + call pctcft(n)%set_pct_l2g(0._r8) + pctlak(n) = 0._r8 + pcturb(n) = 0._r8 + pctgla(n) = 0._r8 + pctwet(n) = 0._r8 + pctocn(n) = 100._r8 ! the only asignment of non-zero ocean + else + ! Fill the rest of the land area with natveg, then renormalize landunits so + ! that they are expressed as percent of the land area rather than percent of + ! the full gridcell area. + + ! First fill the rest of the land area with natveg: + new_total_natveg_pct = pct_land - suma + ! Based on the formulation of pct_land above, pct_land is guaranteed to be at + ! least as large as suma. However, correct it just in case there is rounding + ! error: + new_total_natveg_pct = max(new_total_natveg_pct, 0._r8) + + ! Now renormalize landunit areas so they are expressed as percent of the land + ! area rather than percent of the total gridcell area. Note that we have + ! already corrected pct_land above so that if it was slightly less than 100 + ! it was set to exactly 100, so we can check for any values less than 100 + ! here (rather than having some tolerance): + frac_land = pct_land / 100._r8 + if (pct_land < 100._r8) then + new_total_natveg_pct = new_total_natveg_pct / frac_land + call pctcft(n)%set_pct_l2g(pctcft(n)%get_pct_l2g() / frac_land) + pctlak(n) = pctlak(n) / frac_land + pcturb(n) = pcturb(n) / frac_land + pctgla(n) = pctgla(n) / frac_land + pctwet(n) = pctwet(n) / frac_land + end if + + ! Finally, set the actual pct_natveg: + call pctnatpft(n)%set_pct_l2g(new_total_natveg_pct) + end if + + ! Save landfrac for output to file + landfrac_mksurfdata(n) = frac_land + + ! Confirm that we have done the rescaling correctly: now the sum of all landunits + ! should be 100% within tol_loose + suma = pctlak(n) + pctwet(n) + pctgla(n) + pcturb(n) + pctocn(n) + & + pctcft(n)%get_pct_l2g() + pctnatpft(n)%get_pct_l2g() + if (abs(suma - 100._r8) > tol_loose) then + write(ndiag,*) subname, ' ERROR: landunits do not sum to 100%' + write(ndiag,*) 'n, suma, pctlak, pctwet, pctgla, pcturb, pctnatveg, pctcrop, pctocn = ' + write(ndiag,*) n, suma, pctlak(n), pctwet(n), pctgla(n), pcturb(n), & + pctnatpft(n)%get_pct_l2g(), pctcft(n)%get_pct_l2g(), pctocn(n) + flush(ndiag) + call shr_sys_abort() + end if + + end do + + ! ------------------------------------------------------------------------ + ! Do other corrections and error checks + ! ------------------------------------------------------------------------ + + nsmall_tot = 0 + + do n = 1,ns_o + + ! If the coverage of any PFT or CFT is too small at the gridcell level, set its + ! % cover to 0, then renormalize everything else as needed + call pctnatpft(n)%remove_small_cover(toosmallPFT, nsmall) + nsmall_tot = nsmall_tot + nsmall + call pctcft(n)%remove_small_cover(toosmallPFT, nsmall) + nsmall_tot = nsmall_tot + nsmall + + ! Include pctocn in suma but do not include in the + ! renormalization. When pctocn /= 0, it is 100, and + ! all other terms are 0. + suma = pctlak(n) + pctwet(n) + pcturb(n) + pctgla(n) + pctocn(n) + & + pctnatpft(n)%get_pct_l2g() + pctcft(n)%get_pct_l2g() + if ( abs(suma - 100.0_r8) > 2.0*epsilon(suma) )then + pctlak(n) = pctlak(n) * 100._r8/suma + pctwet(n) = pctwet(n) * 100._r8/suma + pcturb(n) = pcturb(n) * 100._r8/suma + pctgla(n) = pctgla(n) * 100._r8/suma + call pctnatpft(n)%set_pct_l2g(pctnatpft(n)%get_pct_l2g() * 100._r8/suma) + call pctcft(n)%set_pct_l2g(pctcft(n)%get_pct_l2g() * 100._r8/suma) + end if + + ! This roundoff error fix is needed to handle the situation where new_total_natveg_pct + ! ends up near 0 but not exactly 0 due to roundoff issues. In this situation, we set the + ! natveg landunit area to exactly 0 and put the remainder into some other landunit. Since + ! the remainder is very small, it doesn't really matter which other landunit we add it to, + ! so we just pick some landunit that already has at least 1% cover. + suma = pctlak(n) + pctwet(n) + pcturb(n) + pctgla(n) + pctcft(n)%get_pct_l2g() + if ( (suma < 100._r8 .and. suma > (100._r8 - 1.e-6_r8)) .or. & + (pctnatpft(n)%get_pct_l2g() > 0.0_r8 .and. pctnatpft(n)%get_pct_l2g() < 1.e-6_r8) ) then + if ( root_task ) then + write (ndiag,*) 'Special plus crop land units near 100%, but not quite for n,suma =',n,suma + write (ndiag,*) 'Adjusting special plus crop land units to 100%' + flush(ndiag) + end if + if (pctlak(n) >= 1.0_r8) then + pctlak(n) = 100._r8 - (pctwet(n) + pcturb(n) + pctgla(n) + pctcft(n)%get_pct_l2g()) + else if (pctwet(n) >= 1.0_r8) then + pctwet(n) = 100._r8 - (pctlak(n) + pcturb(n) + pctgla(n) + pctcft(n)%get_pct_l2g()) + else if (pcturb(n) >= 1.0_r8) then + pcturb(n) = 100._r8 - (pctlak(n) + pctwet(n) + pctgla(n) + pctcft(n)%get_pct_l2g()) + else if (pctgla(n) >= 1.0_r8) then + pctgla(n) = 100._r8 - (pctlak(n) + pctwet(n) + pcturb(n) + pctcft(n)%get_pct_l2g()) + else if (pctcft(n)%get_pct_l2g() >= 1.0_r8) then + call pctcft(n)%set_pct_l2g(100._r8 - (pctlak(n) + pctwet(n) + pcturb(n) + pctgla(n))) + else + write (ndiag,*) subname, 'Error: sum of special plus crop land units nearly 100% but none is >= 1% at ', & + 'n,pctlak(n),pctwet(n),pcturb(n),pctgla(n),pctnatveg(n),pctcrop(n),suma = ', & + n,pctlak(n),pctwet(n),pcturb(n),pctgla(n),& + pctnatpft(n)%get_pct_l2g(),pctcft(n)%get_pct_l2g(),suma + flush(ndiag) + call shr_sys_abort() + end if + call pctnatpft(n)%set_pct_l2g(0._r8) + end if + if ( any(pctnatpft(n)%get_pct_p2g() > 0.0_r8 .and. pctnatpft(n)%get_pct_p2g() < toosmallPFT ) .or. & + any(pctcft(n)%get_pct_p2g() > 0.0_r8 .and. pctcft(n)%get_pct_p2g() < toosmallPFT )) then + write (6,*) 'pctnatpft or pctcft is small at n=', n + write (6,*) 'pctnatpft%pct_p2l = ', pctnatpft(n)%get_pct_p2l() + write (6,*) 'pctcft%pct_p2l = ', pctcft(n)%get_pct_p2l() + write (6,*) 'pctnatpft%pct_l2g = ', pctnatpft(n)%get_pct_l2g() + write (6,*) 'pctcft%pct_l2g = ', pctcft(n)%get_pct_l2g() + flush(6) + call shr_sys_abort() + end if + + suma = pctlak(n) + pctwet(n) + pcturb(n) + pctgla(n) + pctocn(n) + & + pctcft(n)%get_pct_l2g() + pctnatpft(n)%get_pct_l2g() + if ( abs(suma-100._r8) > 1.e-10_r8) then + write (6,*) subname, ' error: sum of pctocn, pctlak, pctwet,', & + 'pcturb, pctgla, pctnatveg and pctcrop is NOT equal to 100' + write (6,*)'n,pctcon,pctlak,pctwet,pcturb,pctgla,pctnatveg,pctcrop,sum= ', & + n,pctocn(n),pctlak(n),pctwet(n),pcturb(n),pctgla(n),& + pctnatpft(n)%get_pct_l2g(),pctcft(n)%get_pct_l2g(), suma + flush(6) + call shr_sys_abort() + end if + + end do + + ! Make sure that sums at the landunit level all add to 100% + ! (Note that we don't check pctglcmec here, because it isn't computed at the point + ! that this subroutine is called -- but the check of sum(pctglcmec) is done in + ! mkglcmecMod) + ! (Also note that we don't need to check pctnatpft or pctcft, because a similar check + ! is done internally by the pct_pft_type routines.) + do n = 1,ns_o + if (abs(sum(urban_classes(n,:)) - 100._r8) > 1.e-12_r8) then + write(ndiag,*) 'sum(urban_classes(n,:)) != 100: ', n, sum(urban_classes(n,:)) + flush(ndiag) + call shr_sys_abort() + end if + end do + + if (root_task) then + if ( nsmall_tot > 0 )then + write(ndiag,*)'number of small pft = ', nsmall_tot + flush(ndiag) + end if + end if + + end subroutine normalize_and_check_landuse + +end program mksurfdata diff --git a/tools/mksurfdata_esmf/src/mktopostatsMod.F90 b/tools/mksurfdata_esmf/src/mktopostatsMod.F90 new file mode 100644 index 0000000000..fac41a082a --- /dev/null +++ b/tools/mksurfdata_esmf/src/mktopostatsMod.F90 @@ -0,0 +1,299 @@ +module mktopostatsMod + + !----------------------------------------------------------------------- + ! make various topography statistics + !----------------------------------------------------------------------- + + use ESMF + use pio + use shr_kind_mod , only : r8 => shr_kind_r8, r4=>shr_kind_r4 + use shr_sys_mod , only : shr_sys_abort + use mkpioMod , only : mkpio_get_rawdata, pio_iotype, pio_ioformat, pio_iosystem + use mkutilsMod , only : chkerr + use mkvarctl , only : ndiag, root_task, mpicom, std_elev, spval + use mkfileMod , only : mkfile_output + + implicit none + private + + public :: mktopostats ! make topo stddev & mean slope + + type(ESMF_DynamicMask) :: dynamicMask + + logical :: calculate_stddev = .true. + + character(len=*) , parameter :: u_FILE_u = & + __FILE__ + +!=============================================================== +contains +!=============================================================== + + subroutine mktopostats(file_mesh_i, file_data_i, file_data_i_override, mesh_o, pioid_o, rc) + + ! make various topography statistics + ! + use mkdiagnosticsMod, only : output_diagnostics_continuous + use mkchecksMod , only : min_bad, max_bad + ! + ! input/output variables + character(len=*) , intent(in) :: file_mesh_i ! input mesh file name + character(len=*) , intent(in) :: file_data_i ! input data file name + character(len=*) , intent(in) :: file_data_i_override ! input data file name + type(ESMF_Mesh) , intent(in) :: mesh_o ! input model mesh + type(file_desc_t) , intent(inout) :: pioid_o + integer , intent(out) :: rc + ! + ! local variables: + type(ESMF_RouteHandle) :: routehandle + type(ESMF_Mesh) :: mesh_i + type(ESMF_Field) :: field_i + type(ESMF_Field) :: field_o + type(file_desc_t) :: pioid_i + integer :: ni,no,k + integer :: ns_i, ns_o + real(r4), allocatable :: data_i(:) + real(r4), pointer :: dataptr(:) + real(r4), allocatable :: topo_stddev_o(:) ! output grid: standard deviation of elevation (m) + real(r4), allocatable :: slope_o(:) ! output grid: slope (degrees) + integer :: ier, rcode ! error status + integer :: srcTermProcessing_Value = 0 + real(r4), parameter :: min_valid = 0._r4 ! minimum valid value + real(r4), parameter :: min_valid_topo_stddev = 0._r4 + real(r4), parameter :: min_valid_slope = 0._r4 + real(r4), parameter :: max_valid_slope = 90._r4 + character(len=*), parameter :: subname = 'mktopostats' + !----------------------------------------------------------------------- + + if (root_task) then + write(ndiag,*) + write(ndiag,'(1x,80a1)') ('=',k=1,80) + write(ndiag,*) + write(ndiag,'(a)') 'Attempting to make Topography statistics.....' + write(ndiag,'(a)') ' Input file is '//trim(file_data_i) + write(ndiag,'(a)') ' Input mesh file is '//trim(file_mesh_i) + end if + + if ( std_elev >= 0.0_r8 )then + if (root_task) then + write (ndiag,'(a)')' Bypass the reading and just use global values' + write (ndiag,'(a)')' Setting std deviation of topography to ', std_elev + write (ndiag,'(a)')' Setting slope of topography to zero' + end if + topo_stddev_o(:) = std_elev + slope_o = 0.0_r8 + RETURN + end if + + ! Determine ns_o and allocate output data + call ESMF_MeshGet(mesh_o, numOwnedElements=ns_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + allocate (topo_stddev_o(ns_o)) ; topo_stddev_o(:) = spval + allocate (slope_o(ns_o)) ; slope_o(:) = spval + + ! Read file_data_i_override for data that is assumed to already be on the output grid + if (file_data_i_override /= ' ' ) then + if (root_task) write(ndiag, '(a)') trim(subname)//" reading STD_ELEV and SLOPE from "//trim(file_data_i_override) + ! TODO: get dimensions and make sure that they match the dimensions of mesh_o + rcode = pio_openfile(pio_iosystem, pioid_i, pio_iotype, trim(file_data_i_override), pio_nowrite) + call mkpio_get_rawdata(pioid_i, 'STD_ELEV', mesh_o, topo_stddev_o, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call mkpio_get_rawdata(pioid_i, 'SLOPE', mesh_o, slope_o, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + if (root_task) write(ndiag, '(a)') trim(subname)//" writing topo_stddev " + call mkfile_output(pioid_o, mesh_o, 'STD_ELEV', topo_stddev_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkfile_output for STD_ELEV') + call mkfile_output(pioid_o, mesh_o, 'SLOPE', slope_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkfile_output for SLOPE') + call pio_syncfile(pioid_o) + RETURN + end if + + ! Open input data file + ! Read in data with PIO_IOTYPE_NETCDF rather than PIO_IOTYPE_PNETCDF since there are problems + ! with the pnetcdf read of this high resolution data + rcode = pio_openfile(pio_iosystem, pioid_i, PIO_IOTYPE_NETCDF, trim(file_data_i), pio_nowrite) + call ESMF_VMLogMemInfo("After pio_openfile "//trim(file_data_i)) + + ! Read in input mesh + mesh_i = ESMF_MeshCreate(filename=trim(file_mesh_i), fileformat=ESMF_FILEFORMAT_UGRID, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After create mesh_i in "//trim(subname)) + + ! Determine ns_i + call ESMF_MeshGet(mesh_i, numOwnedElements=ns_i, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Read in input data data_i + allocate(data_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort(subname//' error in allocating data_i') + call mkpio_get_rawdata(pioid_i, 'ELEVATION', mesh_i, data_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After mkpio_getrawdata in "//trim(subname)) + + ! Create ESMF fields that will be used below + field_i = ESMF_FieldCreate(mesh_i, ESMF_TYPEKIND_R4, meshloc=ESMF_MESHLOC_ELEMENT, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + field_o = ESMF_FieldCreate(mesh_o, ESMF_TYPEKIND_R4, meshloc=ESMF_MESHLOC_ELEMENT, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! Create a route handle + if (root_task) then + write(ndiag,'(a)') subname//' creating a routehandle ' + end if + call ESMF_FieldRegridStore(field_i, field_o, routehandle=routehandle, & + regridmethod=ESMF_REGRIDMETHOD_CONSERVE, srcTermProcessing=srcTermProcessing_Value, & + ignoreDegenerate=.true., unmappedaction=ESMF_UNMAPPEDACTION_IGNORE, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + if (root_task) then + write(ndiag,'(a)') subname//' finished creating a routehandle ' + end if + call ESMF_VMLogMemInfo("After regridstore in "//trim(subname)) + + ! ----------------------------- + ! Obtain the standard deviation + ! ----------------------------- + + ! Create a dynamic mask object + ! The dynamic mask object further holds a pointer to the routine that will be called in order to + ! handle dynamically masked elements - in this case its DynMaskProc (see below) + call ESMF_DynamicMaskSetR4R8R4(dynamicMask, dynamicMaskRoutine=StdDevProc, handleAllElements=.true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! Interpolate data_i to data_o + call ESMF_FieldGet(field_i, farrayptr=dataptr, rc=rc) + dataptr(:) = data_i(:) + call ESMF_FieldGet(field_o, farrayptr=dataptr, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + dataptr(:) = 0._r4 + + call ESMF_FieldRegrid(field_i, field_o, routehandle=routehandle, dynamicMask=dynamicMask, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_FieldGet(field_o, farrayptr=dataptr, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + topo_stddev_o(:) = dataptr(:) + + ! Check validity of output data + if (min_bad(topo_stddev_o, min_valid_topo_stddev, 'topo_stddev')) then + call shr_sys_abort() + end if + call output_diagnostics_continuous(mesh_i, mesh_o, real(data_i,8), real(topo_stddev_o,8), & + "Topo Std Dev", "m", ndiag=ndiag, rc=rc, nomask=.true.) + + ! ----------------------------- + ! Obtain the slope + ! ----------------------------- + + call mkpio_get_rawdata(pioid_i, 'SLOPE', mesh_i, data_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + call ESMF_FieldGet(field_i, farrayptr=dataptr, rc=rc) + dataptr(:) = data_i(:) + call ESMF_FieldGet(field_o, farrayptr=dataptr, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + dataptr(:) = 0._r4 + + calculate_stddev = .false. ! module variable used by dynamic mask + call ESMF_FieldRegrid(field_i, field_o, routehandle=routehandle, dynamicMask=dynamicMask, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + call ESMF_FieldGet(field_o, farrayptr=dataptr, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + slope_o(:) = dataptr(:) + + ! Check validity of output data + if (min_bad(slope_o, min_valid_slope, 'slope') .or. & + max_bad(slope_o, max_valid_slope, 'slope')) then + call shr_sys_abort() + end if + call output_diagnostics_continuous(mesh_i, mesh_o, real(data_i,8), real(slope_o,8), & + "Slope", "degrees", ndiag=ndiag, rc=rc, nomask=.true.) + + ! Write out output data + if (root_task) write(ndiag, '(a)') trim(subname)//" writing topo_stddev " + call mkfile_output(pioid_o, mesh_o, 'STD_ELEV', topo_stddev_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkfile_output for STD_ELEV') + + if (root_task) write(ndiag, '(a)') trim(subname)//" writing slope" + call mkfile_output(pioid_o, mesh_o, 'SLOPE', slope_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkfile_output for SLOPE') + call pio_syncfile(pioid_o) + + ! Close files and deallocate dynamic memory + call pio_closefile(pioid_i) + call ESMF_RouteHandleDestroy(routehandle, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + call ESMF_MeshDestroy(mesh_i, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + call ESMF_FieldDestroy(field_i, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + call ESMF_FieldDestroy(field_o, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + call ESMF_VMLogMemInfo("After destroy operations in "//trim(subname)) + + if (root_task) then + write (ndiag,'(a)') 'Successfully made Topography statistics' + write (ndiag,'(a)') + end if + + end subroutine mktopostats + + !================================================================================================ + subroutine StdDevProc(dynamicMaskList, dynamicSrcMaskValue, dynamicDstMaskValue, rc) + + use ESMF, only : ESMF_RC_ARG_BAD + + ! input/output arguments + type(ESMF_DynamicMaskElementR4R8R4) , pointer :: dynamicMaskList(:) + real(ESMF_KIND_R4) , intent(in), optional :: dynamicSrcMaskValue + real(ESMF_KIND_R4) , intent(in), optional :: dynamicDstMaskValue + integer , intent(out) :: rc + + ! local variables + integer :: i, j + real(ESMF_KIND_R4) :: renorm + real(ESMF_KIND_R4) :: mean + !--------------------------------------------------------------- + + rc = ESMF_SUCCESS + + ! Below - ONLY if you do NOT have the source masked out then do + ! the regridding (which is done explicitly here) + ! Below i are the destination points and j are the source points + + if (associated(dynamicMaskList)) then + do i=1, size(dynamicMaskList) + dynamicMaskList(i)%dstElement = 0.d0 ! set to zero + renorm = 0.d0 ! reset + + ! Determine the mean + do j = 1, size(dynamicMaskList(i)%factor) + dynamicMaskList(i)%dstElement = dynamicMaskList(i)%dstElement + & + (dynamicMaskList(i)%factor(j) * dynamicMaskList(i)%srcElement(j)) + renorm = renorm + dynamicMaskList(i)%factor(j) + enddo + if (renorm > 0.d0) then + dynamicMaskList(i)%dstElement = dynamicMaskList(i)%dstElement / renorm + else + rc = ESMF_RC_ARG_BAD ! error detected + return + endif + + ! Now compute the standard deviation + if (calculate_stddev) then + mean = dynamicMaskList(i)%dstElement + dynamicMaskList(i)%dstElement = 0.d0 ! reset to zero + do j = 1, size(dynamicMaskList(i)%factor) + dynamicMaskList(i)%dstElement = dynamicMaskList(i)%dstElement + & + (dynamicMaskList(i)%factor(j) * (dynamicMaskList(i)%srcElement(j) - mean)**2) + enddo + dynamicMaskList(i)%dstElement = sqrt(dynamicMaskList(i)%dstElement/renorm) + end if + enddo + endif + + end subroutine StdDevProc + +end module mktopostatsMod diff --git a/tools/mksurfdata_esmf/src/mkurbanparMod.F90 b/tools/mksurfdata_esmf/src/mkurbanparMod.F90 new file mode 100644 index 0000000000..df4bfd43ba --- /dev/null +++ b/tools/mksurfdata_esmf/src/mkurbanparMod.F90 @@ -0,0 +1,1001 @@ +module mkurbanparMod + + !----------------------------------------------------------------------- + ! Make Urban Parameter data + !----------------------------------------------------------------------- + + use ESMF + use pio + use shr_kind_mod , only : r8 => shr_kind_r8, r4 => shr_kind_r4, cs => shr_kind_cs + use shr_sys_mod , only : shr_sys_abort + use mkpioMod , only : mkpio_get_rawdata, pio_iotype, pio_iosystem + use mkpioMod , only : mkpio_iodesc_output, mkpio_get_rawdata + use mkesmfMod , only : regrid_rawdata, create_routehandle_r8 + use mkutilsMod , only : chkerr + use mkvarctl , only : root_task, ndiag, ispval, outnc_double + use mkutilsMod , only : normalize_classes_by_gcell + use mkdiagnosticsMod , only : output_diagnostics_index, output_diagnostics_continuous + use mkindexmapMod , only : dim_slice_type, lookup_2d_netcdf + use mkvarpar , only : numrad, numsolar, re + + implicit none + private + + public :: mkurbanInit + public :: mkurban + public :: mkurbanpar + public :: update_max_array_urban + public :: normalize_urbn_by_tot + public :: mkurban_topo ! Get elevation to reduce urban for high elevation areas + public :: mkurban_pct_diagnostics ! print diagnostics related to pct urban + + ! Note: normalize_urbn_by_tot could be private, but because there + ! are associated test routines in a separate module, it needs to be public + + ! public data members + integer, public :: numurbl ! number of urban classes + integer, public :: nlevurb = ispval ! number of urban layers + integer, public :: nregions + + real(r8), parameter :: MIN_DENS = 0.1_r8 ! minimum urban density (% of grid cell) - below this value, urban % is set to 0 + + ! private data members: + ! flag to indicate nodata for index variables in output file: + integer , parameter :: index_nodata = 0 + real(r8) , allocatable :: frac_o_mkurban_nonorm(:) + type(ESMF_RouteHandle) :: routehandle_mkurban_nonorm + character(len=*), parameter :: modname = 'mkurbanparMod' + + private :: index_nodata + private :: modname + + character(len=*) , parameter :: u_FILE_u = & + __FILE__ + +!=============================================================== +contains +!=============================================================== + + subroutine mkurbanInit(datafname) + ! + ! Initialize variables needed for urban + ! + ! input variables + character(len=*), intent(in) :: datafname ! input data file name (same as file used in mkurban) + ! + ! local variables: + type(file_desc_t) :: pioid + integer :: dimid + integer :: rcode + character(len=*), parameter :: subname = 'mkurbanInit' + !----------------------------------------------------------------------- + + ! Set numurbl, nlevurb and nregions + rcode = pio_openfile(pio_iosystem, pioid, pio_iotype, trim(datafname), pio_nowrite) + rcode = pio_inq_dimid(pioid, 'density_class', dimid) + rcode = pio_inq_dimlen(pioid, dimid, numurbl) + rcode = pio_inq_dimid(pioid, 'nlevurb', dimid) + rcode = pio_inq_dimlen(pioid, dimid, nlevurb) + rcode = pio_inq_dimid(pioid, 'region', dimid) + rcode = pio_inq_dimlen(pioid, dimid, nregions) + call pio_closefile(pioid) + + end subroutine mkurbanInit + + !=============================================================== + subroutine mkurban(file_mesh_i, file_data_i, mesh_o, pcturb_o, & + urban_classes_o, region_o, rc) + ! + ! make total percent urban, breakdown into urban classes, and region ID on the output grid + ! + ! urban_classes_o(n, i) gives the percent of the urban area in grid cell n that is in class #i. + ! This is normalized so that sum(urban_classes_o(n,:)) = 100 for all n, even for grid + ! cells where pcturb_o(n) = 0 (in the case where pcturb_o(n) = 0, we come up with an + ! arbitrary assignment of urban into the different classes). + ! + ! See comments under the normalize_urbn_by_tot subroutine for how urban_classes_o is + ! determined when the total % urban is 0, according to the input data. + ! + ! TODO (WJS 6-12-14): I think this could be rewritten slightly to take advantage of the + ! new mkpctPftTypeMod (which should then be renamed to something more general; or maybe + ! better, in terms of maintaining helpful abstractions, there could be a new type to + ! handle urban, and both that and pct_pft_type could be build on a single set of shared + ! code - either as a single base class or through a "has-a" mechanism). This would allow + ! us to combine pcturb_o and urban_classes_o into a single derived type variable. I think + ! this would also replace the use of normalize_classes_by_gcell, and maybe some other + ! urban-specific code. + ! + ! uses + use mkinputMod, only: mksrf_fdynuse + ! + ! input/output variables + character(len=*) , intent(in) :: file_mesh_i ! input mesh file name + character(len=*) , intent(in) :: file_data_i ! input data file name + type(ESMF_Mesh) , intent(in) :: mesh_o ! model mesh + real(r8) , intent(inout) :: pcturb_o(:) ! output grid: total % urban + real(r8) , intent(inout) :: urban_classes_o(:,:) ! output grid: breakdown of total urban into each class + integer , intent(inout) :: region_o(:) ! output grid: region ID + integer , intent(out) :: rc + + ! local variables: + type(ESMF_Mesh) :: mesh_i + type(file_desc_t) :: pioid + integer , allocatable :: mask_i(:) + real(r8), allocatable :: frac_i(:) + real(r8), allocatable :: data_i(:,:) + real(r8), allocatable :: data_o(:,:) + real(r8), allocatable :: urban_classes_gcell_o(:,:) ! % putput urban in each density class (% of total grid cell area) + integer , allocatable :: region_i(:) ! input grid: region ID + integer :: ni,no ! indices + integer :: ns_i, ns_o ! array sizes + integer :: n,k,l ! indices + integer :: max_regions ! maximum region index + integer :: max_index(1) + integer :: rcode, ier ! error status + character(len=*), parameter :: subname = 'mkurban' + !----------------------------------------------------------------------- + + rc = ESMF_SUCCESS + + if (root_task) then + write(ndiag,*) + write(ndiag,'(1x,80a1)') ('=',k=1,80) + write(ndiag,*) + write(ndiag,'(a)') 'Attempting to make %urban .....' + write(ndiag,'(a)') ' Input file is '//trim(file_data_i) + end if + + ! Open input data file + call ESMF_VMLogMemInfo("Before pio_openfile for "//trim(file_data_i)) + rcode = pio_openfile(pio_iosystem, pioid, pio_iotype, trim(file_data_i), pio_nowrite) + call ESMF_VMLogMemInfo("After pio_openfile "//trim(file_data_i)) + + ! Read in input mesh + call ESMF_VMLogMemInfo("Before create mesh_i in "//trim(subname)) + mesh_i = ESMF_MeshCreate(filename=trim(file_mesh_i), fileformat=ESMF_FILEFORMAT_ESMFMESH, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After create mesh_i in "//trim(subname)) + + ! Determine ns_i + call ESMF_MeshGet(mesh_i, numOwnedElements=ns_i, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Determine ns_o + call ESMF_MeshGet(mesh_o, numOwnedElements=ns_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Get the landmask from the input data file and reset the mesh mask based on that + allocate(frac_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort() + allocate(mask_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort() + call mkpio_get_rawdata(pioid, 'LANDMASK', mesh_i, frac_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + do ni = 1,ns_i + if (frac_i(ni) > 0._r8) then + mask_i(ni) = 1 + else + mask_i(ni) = 0 + end if + end do + call ESMF_MeshSet(mesh_i, elementMask=mask_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! Create a route handle between the input and output mesh + if (.not. ESMF_RouteHandleIsCreated(routehandle_mkurban_nonorm)) then + allocate(frac_o_mkurban_nonorm(ns_o)) + call create_routehandle_r8(mesh_i=mesh_i, mesh_o=mesh_o, norm_by_fracs=.false., & + routehandle=routehandle_mkurban_nonorm, frac_o=frac_o_mkurban_nonorm, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After create routehandle in "//trim(subname)) + end if + + ! Read in input data + ! - levels are the outermost dimension in pio reads + ! - levels are the innermost dimension for esmf fields + ! Input data is read into (ns_i,numurbl) array and then transferred to data_i(numurbl,ns_i) + allocate(data_i(numurbl,ns_i),stat=ier) + if (ier/=0) call shr_sys_abort() + allocate(data_o(numurbl,ns_o),stat=ier) + if (ier/=0) call shr_sys_abort() + call mkpio_get_rawdata(pioid, 'PCT_URBAN', mesh_i, data_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After mkpio_getrawdata in "//trim(subname)) + + ! Regrid input data to model resolution + ! + ! Use a nonorm mapper because we're mapping a field expressed as % of the grid cell area + call regrid_rawdata(mesh_i, mesh_o, routehandle_mkurban_nonorm, data_i, data_o, 1, numurbl, rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After regrid_data for in "//trim(subname)) + + ! Now Determine total % urban + ! urbn_classes_gcell_o is % urban of total grid cell area for each density class + allocate(urban_classes_gcell_o(ns_o, numurbl), stat=ier) + if (ier/=0) call shr_sys_abort() + do l = 1,numurbl + do no = 1,ns_o + urban_classes_gcell_o(no,l) = data_o(l,no) + end do + end do + do no = 1, ns_o + pcturb_o(no) = sum(urban_classes_gcell_o(no,:)) + end do + ! Check for conservation + do no = 1, ns_o + if ((pcturb_o(no)) > 100.000001_r8) then + write (6,'(a,d13.5,a,i8)') trim(subname)//' error: percent urban = ',pcturb_o(no), & + ' greater than 100.000001 for no = ',no + call shr_sys_abort() + end if + enddo + + ! Determine urban_classes_o + ! Make percent urban on output grid, given percent urban on input grid + ! Determine pcturb_o on ouput grid: + call normalize_urbn_by_tot(urban_classes_gcell_o, pcturb_o, urban_classes_o) + call ESMF_LogWrite("After normalize_urbn", ESMF_LOGMSG_INFO) + + ! Handle special cases + ! Note that, for all these adjustments of total urban %, we do not change the breakdown + ! into the different urban classes. In particular: when pcturb_o is set to 0 for a point, + ! the breakdown into the different urban classes is maintained as it was before. + ! Set points to 0% if they fall below a given threshold + do no = 1, ns_o + if (pcturb_o(no) < MIN_DENS) then + pcturb_o(no) = 0._r8 + end if + end do + + ! Print diagnostics + ! TODO: call to mkurban_pct_diagnostics has to be rewritten + ! First, recompute urban_classes_gcell_o, based on any changes we have made to pcturb_o + ! call normalize_classes_by_gcell(urban_classes_o, pcturb_o, urban_classes_gcell_o) + ! do k = 1, numurbl + ! call mkurban_pct_diagnostics(ldomain, tdomain, tgridmap, & + ! urban_classes_gcell_i(:,k), urban_classes_gcell_o(:,k), & + ! ndiag, dens_class=k, frac_dst=frac_dst) + ! end do + + if (root_task) then + write (ndiag,'(a)') 'Successfully made %urban' + end if + + ! ------------------------------------------------------ + ! Read in region field + ! ------------------------------------------------------ + + if (root_task) then + write(ndiag,*) + write(ndiag,'(1x,80a1)') ('=',k=1,80) + write(ndiag,*) + write(ndiag,'(a)') 'Attempting to make urban region .....' + write(ndiag,'(a)') ' Input file is '//trim(file_data_i) + end if + + ! Read in region_i + allocate(region_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort() + call mkpio_get_rawdata(pioid, 'REGION_ID', mesh_i, region_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_LogWrite("After reading in region_id in "//trim(subname), ESMF_LOGMSG_INFO) + max_regions = nregions + if (root_task) then + write(ndiag,'(a,i8)')" max urban regions = ",max_regions + end if + + ! Create a multi-dimensional array (data_i) where each ungridded dimension corresponds to a 2d field + ! where there is a 1 for every gridcell that has region_i equal to a given region + if (allocated(data_i)) deallocate(data_i) + allocate(data_i(max_regions, ns_i), stat=ier) + if (ier/=0) call shr_sys_abort('error allocating data_i(max_regions, ns_i)') + data_i(:,:) = 0._r8 + do l = 1,max_regions + do ni = 1,ns_i + if (region_i(ni) == l) then + data_i(l,ni) = 1._r8 * frac_i(ni) + end if + end do + end do + deallocate(frac_i) + + ! Regrid data_i to data_o + if (allocated(data_o)) deallocate(data_o) + allocate(data_o(max_regions, ns_o), stat=ier) + if (ier/=0) call shr_sys_abort('error allocating data_i(max_regions, ns_o)') + ! This regridding could be done either with or without fracarea normalization, + ! because we just use it to find a dominant value. We use nonorm because we already + ! have a nonorm mapper for the sake of PCTURB and this way we don't need to make a + ! separate mapper with fracarea normalization. + call regrid_rawdata(mesh_i, mesh_o, routehandle_mkurban_nonorm, data_i, data_o, 1, nregions, rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Now find dominant region in each output gridcell - this is identical to the maximum index + region_o(:) = 0 + do no = 1,ns_o + max_index = maxloc(data_o(:,no)) + if (data_o(max_index(1),no) > 0._r8) then + region_o(no) = max_index(1) + end if + end do + + if (root_task) then + write (ndiag,'(a)') 'Successfully made urban region' + write (ndiag,*) + end if + + ! Output diagnostics + call output_diagnostics_index(mesh_i, mesh_o, mask_i, frac_o_mkurban_nonorm, & + 1, max_regions, region_i, region_o, 'urban region', ndiag, rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + + + ! Close the file + call pio_closefile(pioid) + + ! Deallocate dynamic memory & other clean up + ! TODO: determine what to deallocate + ! deallocate (urban_classes_gcell_i, urban_classes_gcell_o, region_i) + if (mksrf_fdynuse == ' ') then ! ...else we will reuse it + deallocate(frac_o_mkurban_nonorm) + call ESMF_VMLogMemInfo("Before destroy operation in "//trim(subname)) + call ESMF_RouteHandleDestroy(routehandle_mkurban_nonorm, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + end if + call ESMF_MeshDestroy(mesh_i, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + call ESMF_VMLogMemInfo("after destroy operation in "//trim(subname)) + + end subroutine mkurban + + !=============================================================== + subroutine normalize_urbn_by_tot(classes_pct_gcell, sums, classes_pct_tot) + ! + ! Normalizes urban class areas to produce % cover of each class, as % of total urban area + ! + ! Specifically: Given (1) an array specifying the % cover of each urban class, as a % of + ! the total grid cell area ('classes_pct_gcell'), and (2) a vector giving the total urban + ! area in each grid cell, expressed as % of the grid cell area: Returns an array + ! ('classes_pct_tot') of the same dimensionality as classes_pct_gcell, where the values + ! now give % cover of each class as a % of the total urban area. + ! + ! Assumes that sums(n) = sum(classes_pct_gcell(n,:)) + ! + ! When sums(n) = 0, the creation of classes_pct_tot(n,:) is ambiguous. Here we use the + ! rule that all area is assigned to the medium-density class, defined by parameter MD. + ! + ! The returned array satisfies sum(classes_pct_tot(n,:))==100 for all n (within rounding error) + + ! input/output variables + real(r8), intent(in) :: classes_pct_gcell(:,:) ! % cover of classes as % of grid cell + real(r8), intent(in) :: sums(:) ! totals, as % of grid cell + real(r8), intent(inout):: classes_pct_tot(:,:) ! % cover of classes as % of total + + ! local variables: + integer :: n ! index + integer :: n_max ! number of points + integer :: nclasses ! number of classes + real(r8) :: suma ! sum for error check + + ! index of medium-density class, which is where we assign urban areas when the total + ! urban area is 0 + integer, parameter :: MD = 3 + + ! relative error tolerance for error check + real(r8), parameter :: relerr = 1.e-10_r8 + + character(len=*), parameter :: subname = 'normalize_urbn_by_tot' + !----------------------------------------------------------------------- + + ! Error-check inputs + n_max = size(sums) + if (size(classes_pct_tot, 1) /= n_max .or. & + size(classes_pct_gcell, 1) /= n_max) then + write(6,*) subname//' ERROR: array size mismatch' + write(6,*) 'size(sums) = ', n_max + write(6,*) 'size(classes_pct_tot, 1) = ', size(classes_pct_tot, 1) + write(6,*) 'size(classes_pct_gcell, 1) = ', size(classes_pct_gcell, 1) + call shr_sys_abort() + end if + if (size(classes_pct_tot, 2) /= size(classes_pct_gcell, 2)) then + write(6,*) subname//' ERROR: array size mismatch' + write(6,*) 'size(classes_pct_tot, 2) = ', size(classes_pct_tot, 2) + write(6,*) 'size(classes_pct_gcell, 2) = ', size(classes_pct_gcell, 2) + call shr_sys_abort() + end if + nclasses = size(classes_pct_gcell, 2) + if (MD > nclasses) then + write(6,*) subname//' ERROR: MD exceeds nclasses' + write(6,*) 'MD = ', MD + write(6,*) 'nclasses = ', nclasses + call shr_sys_abort() + end if + + ! Do the work + do n = 1, n_max + if (sums(n) > 0._r8) then + classes_pct_tot(n,:) = classes_pct_gcell(n,:)/sums(n) * 100._r8 + else + ! Creation of classes_pct_tot is ambiguous. Apply the rule that all area is + ! assigned to the medium-density class. + classes_pct_tot(n,:) = 0._r8 + classes_pct_tot(n,MD) = 100._r8 + end if + end do + + ! Error-check output: Make sure sum(classes_pct_tot(n,:)) = 100 for all n + + do n = 1, n_max + suma = sum(classes_pct_tot(n,:)) + if (abs(suma/100._r8 - 1._r8) > relerr) then + write(6,*) subname//' ERROR: sum does not equal 100 at point ', n + write(6,*) 'suma = ', suma + call shr_sys_abort() + end if + end do + + end subroutine normalize_urbn_by_tot + + !=============================================================== + subroutine mkurbanpar(datfname_i, pioid_o, mesh_o, & + region_o, urban_classes_gcell_o, urban_skip_abort_on_invalid_data_check) + ! + ! Make Urban Parameter data using the information from region_o input + ! + ! Note that, in a grid cell with region_o==r, parameter values are filled from region r + ! for ALL density classes. Thus, the parameter variables have a numurbl dimension along + ! with their other dimensions. + ! + ! Note that we will have a 'nodata' value (given by the fill_val value associated with + ! each parameter) wherever (1) we have a nodata value for region_o, or (2) the parameter + ! has nodata for the given region/density combination in the input lookup table. + ! + ! input/output variables + character(len=*) , intent(in) :: datfname_i ! input data file name + type(file_desc_t) , intent(inout) :: pioid_o ! output file pio id + type(ESMF_Mesh) , intent(in) :: mesh_o ! model mesh + integer , intent(in) :: region_o(:) ! output grid: region ID (length: ns_o) + real(r8) , intent(in) :: urban_classes_gcell_o(:,:) ! output grid: percent urban in each density class + ! (% of total grid cell area) (dimensions: ns_o, numurbl) + logical , intent(in) :: urban_skip_abort_on_invalid_data_check + + ! local variables + ! Type to store information about each urban parameter + type param + character(len=32) :: name ! name in input & output files + real(r8) :: fill_val ! value to put where we have no data in output + logical :: check_invalid ! should we check whether there are any invalid data in the output? + end type param + integer , allocatable :: idata_scalar_o(:,:) ! output array for parameters with no extra dimensions + real(r8), allocatable :: data_scalar_o(:,:) ! output array for parameters with no extra dimensions + real(r8), allocatable :: data_rad_o(:,:,:,:) ! output array for parameters dimensioned by numrad & numsolar + real(r8), allocatable :: data_levurb_o(:,:,:) ! output array for parameters dimensioned by nlevurb + integer , allocatable :: unity_dens_o(:,:) ! artificial density indices + integer :: nlevurb_i ! input grid: number of urban vertical levels + integer :: numsolar_i ! input grid: number of solar type (DIR/DIF) + integer :: numrad_i ! input grid: number of solar bands (VIS/NIR) + integer :: m,n,no,ns_o,p,k ! indices + type(file_desc_t) :: pioid_i + type(var_desc_t) :: pio_varid + type(io_desc_t) :: pio_iodesc + integer :: pio_vartype + integer :: dimid + integer :: ier, rcode, rc ! error status + character(len=cs) :: varname ! variable name + integer :: xtype ! external type + + ! information on extra dimensions for lookup tables greater than 2-d: + type(dim_slice_type), allocatable :: extra_dims(:) + + ! value to put where we have no data in output variables, for real-valued parameters + real(r8), parameter :: fill_val_real = 0._r8 + + ! To add a new urban parameter, simply add an element to one of the below lists + ! (params_scalar, params_rad or params_levurb) + + ! Urban parameters with no extra dimensions + type(param), parameter :: params_scalar(13) = & + (/ param('CANYON_HWR' , fill_val_real, .true.), & ! 1 + param('EM_IMPROAD' , fill_val_real, .true.), & ! 2 + param('EM_PERROAD' , fill_val_real, .true.), & ! 3 + param('EM_ROOF' , fill_val_real, .true.), & ! 4 + param('EM_WALL' , fill_val_real, .true.), & ! 5 + param('HT_ROOF' , fill_val_real, .true.), & ! 6 + param('THICK_ROOF' , fill_val_real, .true.), & ! 7 + param('THICK_WALL' , fill_val_real, .true.), & ! 8 + param('T_BUILDING_MIN' , fill_val_real, .true.), & ! 9 + param('WIND_HGT_CANYON' , fill_val_real, .true.), & ! 10 + param('WTLUNIT_ROOF' , fill_val_real, .true.), & ! 11 + param('WTROAD_PERV' , fill_val_real, .true.), & ! 12 + + ! Note that NLEV_IMPROAD is written as an integer, meaning that type conversion occurs + ! by truncation. Thus we expect the values in the NLEV_IMPROAD lookup table to be exact; + ! e.g., if a value were 1.99999 rather than 2.0000, it would be written as 1 instead of 2 + ! Also note: we use fill_val=-1 rather than 0, because 0 appears in the lookup table + param('NLEV_IMPROAD' , -1 , .true.) /) ! 13 + + ! Urban parameters dimensioned by numrad & numsolar + type(param), parameter :: params_rad(4) = & + (/ param('ALB_IMPROAD' , fill_val_real, .true.), & ! 1 + param('ALB_PERROAD' , fill_val_real, .true.), & ! 2 + param('ALB_ROOF' , fill_val_real, .true.), & ! 3 + param('ALB_WALL' , fill_val_real, .true.) /) ! 4 + + ! suffix for variables dimensioned by numsolar, for each value of numsolar: + character(len=8), parameter :: solar_suffix(numsolar) = (/'_DIR', '_DIF'/) + + ! Urban parameters dimensioned by nlevurb + type(param), parameter :: params_levurb(6) = & + (/ param('TK_ROOF', fill_val_real, .true.), & ! 1 + param('TK_WALL', fill_val_real, .true.), & ! 2 + param('CV_ROOF', fill_val_real, .true.), & ! 3 + param('CV_WALL', fill_val_real, .true.), & ! 4 + + ! Impervious road thermal conductivity and heat capacity have varying levels of + ! data. Thus, we expect to find some missing values in the lookup table -- we + ! do not want to treat that as an error -- thus, we set check_invalid=.false. + param('CV_IMPROAD', fill_val_real, .false.), & ! 5 + param('TK_IMPROAD', fill_val_real, .false.) /) ! 6 + + character(len=*), parameter :: subname = 'mkurbanpar' + !----------------------------------------------------------------------- + + if (root_task) then + write (ndiag,'(a)') 'Attempting to make Urban Parameters .....' + end if + + ! Determine & error-check array sizes + ns_o = size(region_o) + if (size(urban_classes_gcell_o, 1) /= ns_o) then + write(6,*) modname//':'//subname//' ERROR: array size mismatch' + write(6,*) 'size(region_o) = ', size(region_o) + write(6,*) 'size(urban_classes_gcell_o, 1) = ', size(urban_classes_gcell_o, 1) + call shr_sys_abort() + end if + if (size(urban_classes_gcell_o, 2) /= numurbl) then + write(6,*) modname//':'//subname//' ERROR: array size mismatch' + write(6,*) 'size(urban_classes_gcell_o, 2) = ', size(urban_classes_gcell_o, 2) + write(6,*) 'numurbl = ', numurbl + end if + + ! Read dimensions from input file + if (root_task) then + write (ndiag,'(a)') 'Opening input urban parameter file: '//trim(datfname_i) + end if + rcode = pio_openfile(pio_iosystem, pioid_i, pio_iotype, trim(datfname_i), pio_nowrite) + rcode = pio_inq_dimid(pioid_i, 'nlevurb', dimid) + rcode = pio_inq_dimlen(pioid_i, dimid, nlevurb_i) + rcode = pio_inq_dimid(pioid_i, 'numsolar', dimid) + rcode = pio_inq_dimlen(pioid_i, dimid, numsolar_i) + rcode = pio_inq_dimid(pioid_i, 'numrad', dimid) + rcode = pio_inq_dimlen(pioid_i, dimid, numrad_i) + + if (nlevurb_i /= nlevurb) then + write(6,*)'MKURBANPAR: parameter nlevurb= ',nlevurb, & + 'does not equal input dataset nlevurb= ',nlevurb_i + call shr_sys_abort() + endif + if (numsolar_i /= numsolar) then + write(6,*)'MKURBANPAR: parameter numsolar= ',numsolar, & + 'does not equal input dataset numsolar= ',numsolar_i + call shr_sys_abort() + endif + if (numrad_i /= numrad) then + write(6,*)'MKURBANPAR: parameter numrad= ',numrad, & + 'does not equal input dataset numrad= ',numrad_i + call shr_sys_abort() + endif + + ! Create an array that will hold the density indices + ! In a given grid cell, we output parameter values for all density classes, for the + ! region of that grid cell. In order to do this while still using the lookup_2d + ! routine, we create a dummy unity_dens_o array that contains the density values + ! passed to the lookup routine. + + allocate(unity_dens_o(ns_o, numurbl)) + do k = 1, numurbl + unity_dens_o(:,k) = k + end do + + ! ------------------------------------------------ + ! Handle urban parameters with no extra dimensions + ! ------------------------------------------------ + + allocate(data_scalar_o(ns_o, numurbl), stat=ier) + data_scalar_o(:,:) = 0._r8 + if (ier /= 0) call shr_sys_abort('mkurbanpar allocation error') + + do p = 1, size(params_scalar) + ! get variable output (data_scalar_o) + call lookup_and_check_err(pioid_i, params_scalar(p)%name, params_scalar(p)%fill_val, & + params_scalar(p)%check_invalid, urban_skip_abort_on_invalid_data_check, & + data_scalar_o, n_extra_dims = 0) + + ! get io descriptor for variable output, write out variable and free memory for io descriptor + call mkpio_iodesc_output(pioid_o, mesh_o, params_scalar(p)%name, pio_iodesc, rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in generating an iodesc for '//& + trim(params_scalar(p)%name)) + rcode = pio_inq_varid(pioid_o, params_scalar(p)%name, pio_varid) + rcode = pio_inq_vartype(pioid_o, pio_varid, pio_vartype) + if (pio_vartype == PIO_INT) then + allocate(idata_scalar_o(ns_o, numurbl)) + idata_scalar_o(:,:) = int(data_scalar_o) + call pio_write_darray(pioid_o, pio_varid, pio_iodesc, idata_scalar_o(:,:), rcode) + deallocate(idata_scalar_o) + else + call pio_write_darray(pioid_o, pio_varid, pio_iodesc, data_scalar_o(:,:), rcode) + end if + call pio_freedecomp(pioid_o, pio_iodesc) + end do + + deallocate(data_scalar_o) + + ! ------------------------------------------------ + ! Handle urban parameters dimensioned by numrad & numsolar + ! ------------------------------------------------ + + allocate(data_rad_o(ns_o, numurbl, numrad, numsolar), stat=ier) + if (ier /= 0) call shr_sys_abort('mkurbanpar allocation error for data_rad_o') + + allocate(extra_dims(2)) + extra_dims(1)%name = 'numrad' + extra_dims(2)%name = 'numsolar' + + do p = 1, size(params_rad) + + ! Get variable output (data_rad_o) + do m = 1,numsolar + extra_dims(2)%val = m + do n = 1,numrad + extra_dims(1)%val = n + call lookup_and_check_err(pioid_i, params_rad(p)%name, params_rad(p)%fill_val, & + params_rad(p)%check_invalid, urban_skip_abort_on_invalid_data_check, & + data_rad_o(:,:,n,m), n_extra_dims=2, extra_dims=extra_dims) + end do + end do + + ! Special handling of numsolar: rather than outputting variables with a numsolar + ! dimension, we output separate variables for each value of numsolar + do m = 1,numsolar + if (len_trim(params_rad(p)%name) + len_trim(solar_suffix(m)) > len(varname)) then + write(6,*) 'variable name exceeds length of varname' + write(6,*) trim(params_rad(p)%name)//trim(solar_suffix(m)) + call shr_sys_abort() + end if + + ! Determine variable name + varname = trim(params_rad(p)%name)//trim(solar_suffix(m)) + + ! get io descriptor for variable output, write out variable and free memory for io descriptor + call mkpio_iodesc_output(pioid_o, mesh_o, varname, pio_iodesc, rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in generating an iodesc for '//& + trim(params_scalar(p)%name)) + rcode = pio_inq_varid(pioid_o, varname, pio_varid) + call pio_write_darray(pioid_o, pio_varid, pio_iodesc, data_rad_o(:,:,:,m), rcode) + call pio_freedecomp(pioid_o, pio_iodesc) + end do + + end do + + deallocate(data_rad_o) + deallocate(extra_dims) + + ! ------------------------------------------------ + ! Handle urban parameters dimensioned by nlevurb + ! ------------------------------------------------ + + allocate(data_levurb_o(ns_o, numurbl, nlevurb), stat=ier) + if (ier /= 0) call shr_sys_abort('mkurbanpar allocation error for data_levurb_o') + + allocate(extra_dims(1)) + extra_dims(1)%name = 'nlevurb' + + do p = 1, size(params_levurb) + do n = 1,nlevurb + extra_dims(1)%val = n + call lookup_and_check_err(pioid_i, params_levurb(p)%name, params_levurb(p)%fill_val, & + params_levurb(p)%check_invalid, & + urban_skip_abort_on_invalid_data_check, data_levurb_o(:,:,n), & + n_extra_dims=1, extra_dims=extra_dims) + end do + + ! get io descriptor for variable output, write out variable and free memory for io descriptor + call mkpio_iodesc_output(pioid_o, mesh_o, params_levurb(p)%name, pio_iodesc, rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in generating an iodesc for '//& + trim(params_levurb(p)%name)) + rcode = pio_inq_varid(pioid_o, params_levurb(p)%name, pio_varid) + call pio_write_darray(pioid_o, pio_varid, pio_iodesc, data_levurb_o(:,:,:), rcode) + call pio_freedecomp(pioid_o, pio_iodesc) + end do + + deallocate(data_levurb_o) + deallocate(extra_dims) + + ! Close input data file + call pio_closefile(pioid_i) + + if (root_task) then + write (ndiag,'(a)') 'Successfully made Urban Parameters' + write (ndiag,'(a)') + end if + + deallocate(unity_dens_o) + + contains + + !------------------------------------------------------------------------------ + subroutine lookup_and_check_err(pioid, varname, fill_val, check_invalid, & + urban_skip_abort_on_invalid_data_check, data, n_extra_dims, extra_dims) + + ! Wrapper to lookup_2d_netcdf: Loops over each density class, calling lookup_2d_netcdf + ! with that density class and filling the appropriate slice of the data array. Also + ! checks for any errors, aborting if there were any. + ! + ! Note that the lookup_2d_netcdf routine is designed to work with a single value of + ! each of the indices. However, we want to fill parameter values for ALL density + ! classes. This is why we loop over density class in this routine. + ! + ! Note: inherits a number of variables from the parent routine + ! + ! input/output variables + type(file_desc_t) , intent(inout) :: pioid + character(len=*) , intent(in) :: varname ! name of lookup table + real(r8) , intent(in) :: fill_val ! value to put where we have no data in output variables + logical , intent(in) :: check_invalid ! should we check whether there are any invalid data in the output? + logical , intent(in) :: urban_skip_abort_on_invalid_data_check + real(r8) , intent(inout) :: data(:,:) ! output from lookup_2d_netcdf + integer , intent(in) :: n_extra_dims ! number of extra dimensions in the lookup table + + ! slice to use if lookup table variable has more than 2 dimensions: + type(dim_slice_type), intent(in), optional :: extra_dims(:) + + ! Local variables: + integer :: k,n ! indices + integer :: ierr ! error return code + !----------------------------------------------------------------------- + + do k = 1, numurbl + ! In the following, note that unity_dens_o(:,k) has been constructed so that + ! unity_dens_o(:,k)==k everywhere. Thus, we fill data(:,k) with the parameter + ! values corresponding to density class k. + ! Also note: We use invalid_okay=.true. because we fill all density classes, + ! some of which may have invalid entries. Because doing so disables some error + ! checking, we do our own error checking after the call. + + call lookup_2d_netcdf(pioid = pioid, & + tablename = varname, & + lookup_has_invalid = .true., & + dimname1 = 'density_class', & + dimname2 = 'region', & + n_extra_dims = n_extra_dims, & + index1 = unity_dens_o(:,k), & + index2 = region_o, & + fill_val = fill_val, & + data = data(:,k), & + ierr = ierr, & + extra_dims= extra_dims, & + nodata = index_nodata, & + invalid_okay = .true.) + if (ierr /= 0) then + write(6,*) modname//':'//subname//' ERROR in lookup_2d_netcdf for ', & + trim(varname), ' class', k, ': err=', ierr + call shr_sys_abort() + end if + + if (check_invalid) then + ! Make sure we have valid parameter values wherever we have non-zero urban cover + do n = 1, ns_o + ! This check assumes that fill_val doesn't appear in any of the valid entries + ! of the lookup table + if (urban_classes_gcell_o(n,k) > 0. .and. data(n,k) == fill_val) then + write(6,*) modname//':'//subname//' ERROR: fill value found in output where urban cover > 0' + write(6,*) 'var: ', trim(varname) + write(6,*) 'class: ', k + write(6,*) 'n: ', n + write(6,*) 'region: ', region_o(n) + write(6,*) 'urban_classes_gcell_o(n,k): ', urban_classes_gcell_o(n,k) + if (.not. urban_skip_abort_on_invalid_data_check) then + ! NOTE(bja, 2015-01) added to work around a ?bug? noted in + ! /glade/campaign/cesm/cesmdata/inputdata/lnd/clm2/surfdata_map/README_c141219 + call shr_sys_abort() + end if + end if + end do + end if + end do + end subroutine lookup_and_check_err + + end subroutine mkurbanpar + + !=============================================================== + subroutine mkurban_pct_diagnostics(area_i, area_o, mask_i, frac_o, urbn_i, urbn_o, dens_class) + ! + ! print diagnostics related to pct urban + ! Compare global areas on input and output grids + ! + ! This is intended to be called after mkurban_pct, but is split out into a separate + ! routine so that modifications to urbn_o can be made in between the two calls (e.g., + ! setting urbn_o to 0 wherever it is less than a certain threshold; the rules for doing + ! this can't always be applied inline in mkurban_pct). + ! + ! input/output variables + real(r8) , intent(in) :: area_i(:) + real(r8) , intent(in) :: area_o(:) + integer , intent(in) :: mask_i(:) + real(r8) , intent(in) :: frac_o(:) + real(r8) , intent(in) :: urbn_i(:) ! input grid: percent urban + real(r8) , intent(in) :: urbn_o(:) ! output grid: percent urban + integer , intent(in), optional :: dens_class ! density class + + ! local variables: + real(r8) :: gurbn_i ! input grid: global urbn + real(r8) :: garea_i ! input grid: global area + real(r8) :: gurbn_o ! output grid: global urbn + real(r8) :: garea_o ! output grid: global area + integer :: ni,no,k ! indices + character(len=*), parameter :: subname = 'mkurban_pct_diagnostics' + !----------------------------------------------------------------------- + + ! Input grid + gurbn_i = 0._r8 + garea_i = 0._r8 + do ni = 1, size(area_i) + garea_i = garea_i + area_i(ni)*re**2 + gurbn_i = gurbn_i + urbn_i(ni)*(area_i(ni)/100._r8)* mask_i(ni)*re**2 + end do + + ! Output grid + gurbn_o = 0._r8 + garea_o = 0._r8 + do no = 1, size(area_o) + garea_o = garea_o + area_o(no)*re**2 + gurbn_o = gurbn_o + urbn_o(no)* (area_o(no)/100._r8)*frac_o(no)*re**2 + end do + + ! Diagnostic output + write (ndiag,*) + write (ndiag,'(1x,70a1)') ('=',k=1,70) + if (present(dens_class)) then + write (ndiag,'(1x,a,i0)') 'Urban Output -- class ', dens_class + else + write (ndiag,'(1x,a)') 'Urban Output' + end if + write (ndiag,'(1x,70a1)') ('=',k=1,70) + write (ndiag,*) + write (ndiag,'(1x,70a1)') ('.',k=1,70) + write (ndiag,2001) +2001 format (1x,'surface type input grid area output grid area'/& + 1x,' 10**6 km**2 10**6 km**2 ') + write (ndiag,'(1x,70a1)') ('.',k=1,70) + write (ndiag,*) + write (ndiag,2003) gurbn_i*1.e-06,gurbn_o*1.e-06 + write (ndiag,2004) garea_i*1.e-06,garea_o*1.e-06 +2002 format (1x,'urban ',f14.3,f17.3) +2003 format (1x,'urban ',f14.3,f22.8) +2004 format (1x,'all surface ',f14.3,f17.3) + + end subroutine mkurban_pct_diagnostics + + !=============================================================== + subroutine mkurban_topo(file_mesh_i, file_data_i, mesh_o, varname, elev_o, rc) + ! + ! Make elevation data + ! + ! input/output variables + character(len=*) , intent(in) :: file_mesh_i ! input mesh file name + character(len=*) , intent(in) :: file_data_i ! input data file name + type(ESMF_Mesh) , intent(in) :: mesh_o ! model mesh + character(len=*) , intent(in) :: varname ! topo variable name + real(r8) , intent(inout) :: elev_o(:) ! output elevation data + integer , intent(out) :: rc + + ! local variables: + type(ESMF_RouteHandle) :: routehandle + type(ESMF_Mesh) :: mesh_i + type(file_desc_t) :: pioid + real(r8), allocatable :: frac_o(:) + real(r8), allocatable :: data_i(:,:) + real(r8), allocatable :: data_o(:,:) + real(r8), allocatable :: elev_i(:) ! canyon_height to width ratio in + integer :: ns_i,ns_o ! bounds + integer :: ni, no ! indices + integer :: k,l,n,m ! indices + character(len=CS) :: name ! name of attribute + character(len=CS) :: unit ! units of attribute + integer :: ier,rcode ! error status + character(len=*), parameter :: subname = 'mkelev' + !----------------------------------------------------------------------- + + rc = ESMF_SUCCESS + + if (root_task) then + write(ndiag,*) + write(ndiag,'(1x,80a1)') ('=',k=1,80) + write(ndiag,*) + write(ndiag,'(a)') 'Attempting to make urban topo elevation .....' + write(ndiag,'(a)') ' Input file is '//trim(file_data_i) + end if + + ! Open input data file + call ESMF_VMLogMemInfo("Before pio_openfile for "//trim(file_data_i)) + rcode = pio_openfile(pio_iosystem, pioid, pio_iotype, trim(file_data_i), pio_nowrite) + call ESMF_VMLogMemInfo("After pio_openfile "//trim(file_data_i)) + + ! Read in input mesh + call ESMF_VMLogMemInfo("Before create mesh_i in "//trim(subname)) + mesh_i = ESMF_MeshCreate(filename=trim(file_mesh_i), fileformat=ESMF_FILEFORMAT_ESMFMESH, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After create mesh_i in "//trim(subname)) + + ! Determine ns_i + call ESMF_MeshGet(mesh_i, numOwnedElements=ns_i, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Determine ns_o + call ESMF_MeshGet(mesh_o, numOwnedElements=ns_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Read topo elev dataset with unit mask everywhere + allocate(elev_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort() + call mkpio_get_rawdata(pioid, trim(varname), mesh_i, elev_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call pio_closefile(pioid) + + ! Create a route handle between the input and output mesh + allocate(frac_o(ns_o), stat=ier) + if (ier/=0) call shr_sys_abort() + call create_routehandle_r8(mesh_i=mesh_i, mesh_o=mesh_o, norm_by_fracs=.true., & + routehandle=routehandle, frac_o=frac_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After create routehandle in "//trim(subname)) + + ! Regrid input data to model resolution - determine elev_o on output grid + elev_o(:) = 0. + if (ier/=0) call shr_sys_abort() + call regrid_rawdata(mesh_i, mesh_o, routehandle, elev_i, elev_o, rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + call output_diagnostics_continuous(mesh_i, mesh_o, elev_i, elev_o, & + "Urban elev variable", "m", ndiag=ndiag, rc=rc, nomask=.true.) + + ! Deallocate dynamic memory + deallocate (elev_i) + deallocate (frac_o) + call ESMF_RouteHandleDestroy(routehandle, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + + if (root_task) then + write (ndiag,'(a)') 'Successfully made elevation' + write (ndiag,'(a)') + end if + + end subroutine mkurban_topo + + !=============================================================== + subroutine update_max_array_urban(pct_urbmax_arr,pct_urban_arr) + ! + ! !DESCRIPTION: + ! Update the maximum percent cover of each urban class for landuse.timeseries file + ! + ! !ARGUMENTS: + real(r8) , intent(inout):: pct_urbmax_arr(:,:) ! max percent cover of each urban class + real(r8) , intent(in):: pct_urban_arr(:,:) ! percent cover of each urban class that is used to update the old pct_urbmax_arr + ! + ! !LOCAL VARIABLES: + integer :: n,k,ns ! indices + + character(len=*), parameter :: subname = 'update_max_array_urban' + !----------------------------------------------------------------------- + ns = size(pct_urban_arr,1) + do n = 1, ns + do k =1, numurbl + if (pct_urban_arr(n,k) > pct_urbmax_arr(n,k)) then + pct_urbmax_arr(n,k) = pct_urban_arr(n,k) + end if + end do + end do + + end subroutine update_max_array_urban + +end module mkurbanparMod diff --git a/tools/mksurfdata_esmf/src/mkutilsMod.F90 b/tools/mksurfdata_esmf/src/mkutilsMod.F90 new file mode 100644 index 0000000000..5b61540a14 --- /dev/null +++ b/tools/mksurfdata_esmf/src/mkutilsMod.F90 @@ -0,0 +1,182 @@ +module mkutilsMod + + + ! General-purpose utilities + use ESMF + use shr_kind_mod, only : r8 => shr_kind_r8, r4 => shr_kind_r4 + use shr_sys_mod , only : shr_sys_abort + + implicit none + private + + ! PUBLIC MEMBER FUNCTIONS: + public :: normalize_classes_by_gcell ! renormalize array so values are given as % of total grid cell area + public :: slightly_below + public :: slightly_above + public :: get_filename !Returns filename given full pathname + public :: chkerr + + character(len=*) , parameter :: u_FILE_u = & + __FILE__ + +!=============================================================== +contains +!=============================================================== + + subroutine normalize_classes_by_gcell(classes_pct_tot, sums, classes_pct_gcell) + ! + ! Renormalizes an array (gcell x class) so that values are given as % of total grid cell area + ! + ! Specifically: Given (1) an array specifying the % cover of different classes, as a % of + ! some total ('classes_pct_tot'), and (2) a vector giving these totals ('sums'), expressed + ! as % of grid cell area: Returns an array ('classes_pct_gcell') of the same + ! dimensionality as classes_pct_tot, where the values now give the % cover of each class + ! as a % of total grid cell area. + ! + ! The size of 'sums' should match the size of the first dimension in 'classes_pct_tot' and + ! 'classes_pct_gcell' + ! + ! For example, if classes_pct_tot(n,i) gives the % of the urban area in grid cell n that is + ! in urban class #i, and sums(n) gives the % of grid cell n that is urban, then + ! classes_pct_gcell(n,i) will give the % of the total area of grid cell n that is in urban + ! class #i. + ! + ! input/output variables + real(r8), intent(in) :: classes_pct_tot(:,:) ! % cover of classes as % of total + real(r8), intent(in) :: sums(:) ! totals, as % of grid cell + real(r8), intent(out):: classes_pct_gcell(:,:) ! % cover of classes as % of grid cell + ! + ! local variables + integer :: n, n_max + character(len=*), parameter :: subname = "normalize_classes_by_gcell" + !------------------------------------------------------------------------------ + + ! Error-check inputs + + n_max = size(sums) + if (size(classes_pct_tot, 1) /= n_max .or. & + size(classes_pct_gcell, 1) /= n_max) then + write(6,*) subname//' ERROR: array size mismatch' + write(6,*) 'size(sums) = ', n_max + write(6,*) 'size(classes_pct_tot, 1) = ', size(classes_pct_tot, 1) + write(6,*) 'size(classes_pct_gcell, 1) = ', size(classes_pct_gcell, 1) + call shr_sys_abort() + end if + + if (size(classes_pct_tot, 2) /= size(classes_pct_gcell, 2)) then + write(6,*) subname//' ERROR: array size mismatch' + write(6,*) 'size(classes_pct_tot, 2) = ', size(classes_pct_tot, 2) + write(6,*) 'size(classes_pct_gcell, 2) = ', size(classes_pct_gcell, 2) + call shr_sys_abort() + end if + + ! Do the work + + do n = 1, n_max + classes_pct_gcell(n,:) = classes_pct_tot(n,:) * (sums(n)/100._r4) + end do + end subroutine normalize_classes_by_gcell + + !=============================================================== + logical function slightly_below(a, b, eps) + + ! Returns true if a is slightly below b; false if a is significantly below b or if a is + ! greater than or equal to b + ! if provided, eps gives the relative error allowed for checking the "slightly" + ! condition; if not provided, the tolerance defaults to the value given by eps_default + + ! !ARGUMENTS: + real(r8), intent(in) :: a + real(r8), intent(in) :: b + real(r8), intent(in), optional :: eps + + ! !LOCAL VARIABLES: + real(r8) :: l_eps + real(r8), parameter :: eps_default = 1.e-15_r8 ! default relative error tolerance + !------------------------------------------------------------------------------ + + if (present(eps)) then + l_eps = eps + else + l_eps = eps_default + end if + + if (a < b .and. (b - a)/b < l_eps) then + slightly_below = .true. + else + slightly_below = .false. + end if + + end function slightly_below + + !=============================================================== + logical function slightly_above(a, b, eps) + + ! Returns true if a is slightly above b; false if a is significantly above b or if a is + ! less than or equal to b + ! + ! if provided, eps gives the relative error allowed for checking the "slightly" + ! condition; if not provided, the tolerance defaults to the value given by eps_default + + ! input/output variables + real(r8), intent(in) :: a + real(r8), intent(in) :: b + real(r8), intent(in), optional :: eps + + ! local variables: + real(r8) :: l_eps + real(r8), parameter :: eps_default = 1.e-15_r8 ! default relative error tolerance + !------------------------------------------------------------------------------ + + if (present(eps)) then + l_eps = eps + else + l_eps = eps_default + end if + + if (a > b .and. (a - b)/b < l_eps) then + slightly_above = .true. + else + slightly_above = .false. + end if + + end function slightly_above + + !=============================================================== + logical function chkerr(rc, line, file) + integer , intent(in) :: rc + integer , intent(in) :: line + character(len=*) , intent(in) :: file + + ! local variables + integer :: lrc + chkerr = .false. + lrc = rc + if (ESMF_LogFoundError(rcToCheck=lrc, msg=ESMF_LOGERR_PASSTHRU, line=line, file=file)) then + chkerr = .true. + endif + end function chkerr + + !=============================================================== + character(len=256) function get_filename (fulpath) + ! Returns filename given full pathname + + ! input/output variables + character(len=*), intent(in) :: fulpath !full pathname + + ! local variables: + integer :: i !loop index + integer :: klen !length of fulpath character string + !------------------------------------------------------------------------ + + klen = len_trim(fulpath) + do i = klen, 1, -1 + if (fulpath(i:i) == '/') go to 10 + end do + i = 0 +10 get_filename = fulpath(i+1:klen) + + end function get_filename + + +end module mkutilsMod diff --git a/tools/mksurfdata_esmf/src/mkvarctl.F90 b/tools/mksurfdata_esmf/src/mkvarctl.F90 new file mode 100644 index 0000000000..53e90a9cc8 --- /dev/null +++ b/tools/mksurfdata_esmf/src/mkvarctl.F90 @@ -0,0 +1,38 @@ +module mkvarctl + + !----------------------------------------------------------------------- + ! Module containing control variables + !----------------------------------------------------------------------- + + use shr_kind_mod, only : r8 => shr_kind_r8 + + implicit none + private + + integer, public :: ndiag ! output log unit + logical, public :: root_task = .TRUE.! proc 0 logical for printing msgs + integer, public :: iam ! processor number + integer, public :: npes ! number of processors + integer, public :: mpicom ! communicator group + + logical, public :: outnc_large_files ! output files in 64-bit format for large files + logical, public :: outnc_double ! output ALL data in files as 64-bit + integer, public :: outnc_dims = 2 ! only applicable to lat/lon grids + logical, public :: outnc_1d ! true => output file is 1d + logical, public :: outnc_vic ! true => output VIC fields + logical, public :: outnc_3dglc ! true => output 3D glacier fields + + logical, public :: no_inlandwet ! set wetland to 0% over land; wetland will only be used for ocean points + + integer, public :: numpft = 16 ! number of plant types + integer, public :: nglcec = 10 ! number of elevation classes for glaciers + + ! Variables to override data read in with + real(r8), public :: std_elev = -999.99_r8 ! Standard deviation of elevation (m) to use for entire region + + real(r8), public, parameter :: spval = 1.e36 ! special value + integer, public, parameter :: ispval = -9999 ! special value + integer , public, parameter :: unsetcol = -999 ! flag to indicate soil color NOT set + real(r8), public, parameter :: unsetsoil = -999.99_r8 ! Flag to signify soil texture override not set + +end module mkvarctl diff --git a/tools/mksurfdata_esmf/src/mkvarpar.F90 b/tools/mksurfdata_esmf/src/mkvarpar.F90 new file mode 100644 index 0000000000..38176d1e88 --- /dev/null +++ b/tools/mksurfdata_esmf/src/mkvarpar.F90 @@ -0,0 +1,22 @@ +module mkvarpar + +!----------------------------------------------------------------------- +! Module containing CLM parameters +!----------------------------------------------------------------------- + + use shr_kind_mod, only: r8 => shr_kind_r8 + use shr_const_mod, only: SHR_CONST_REARTH + + implicit none + public + + integer, parameter :: nlevsoi = 10 ! number of soil layers + integer, parameter :: numstdpft = 16 ! number of standard PFT types + integer, parameter :: numstdcft = 2 ! of the number of standard PFT types, how many are crop (CFT) + integer, parameter :: noveg = 0 ! value for non-vegetated pft + integer, parameter :: numsolar = 2 ! number of solar types (Direct,Diffuse) + integer, parameter :: numrad = 2 ! number of solar bands (VIS,NIR) + real(r8),parameter :: elev_thresh = 2600._r8 ! elevation threshold for screening urban areas (m) + real(r8),parameter :: re = SHR_CONST_REARTH * 0.001 ! radius of earth (km) + +end module mkvarpar diff --git a/tools/mksurfdata_esmf/src/mkvocefMod.F90 b/tools/mksurfdata_esmf/src/mkvocefMod.F90 new file mode 100644 index 0000000000..6aa8ba6ec4 --- /dev/null +++ b/tools/mksurfdata_esmf/src/mkvocefMod.F90 @@ -0,0 +1,249 @@ +module mkvocefMod + + !----------------------------------------------------------------------- + ! Make VOC percentage emissions for surface dataset + !----------------------------------------------------------------------- + + use ESMF + use pio + use shr_kind_mod , only : r8 => shr_kind_r8, r4 => shr_kind_r4 + use shr_sys_mod , only : shr_sys_abort + use mkpioMod , only : mkpio_get_rawdata + use mkpioMod , only : mkpio_iodesc_rawdata, pio_iotype, pio_iosystem + use mkesmfMod , only : regrid_rawdata, create_routehandle_r8 + use mkutilsMod , only : chkerr + use mkvarctl , only : root_task, ndiag, mpicom + use mkfileMod , only : mkfile_output + + implicit none + private + + public :: mkvocef ! Get the percentage emissions for VOC for different land cover types + + character(len=*) , parameter :: u_FILE_u = & + __FILE__ + +!================================================================================= +contains +!================================================================================= + + subroutine mkvocef(file_mesh_i, file_data_i, mesh_o, pioid_o, lat_o, rc) + ! + ! make volatile organic coumpunds (VOC) emission factors. + ! + ! input/output variables + character(len=*) , intent(in) :: file_mesh_i ! input mesh file name + character(len=*) , intent(in) :: file_data_i ! input data file name + type(ESMF_Mesh) , intent(in) :: mesh_o ! model mesho + type(file_desc_t) , intent(inout) :: pioid_o ! output file descripter + real(r8) , intent(in) :: lat_o(:) ! output latitudes + integer , intent(out) :: rc + + ! local variables: + type(ESMF_RouteHandle) :: routehandle + type(ESMF_Mesh) :: mesh_i + type(file_desc_t) :: pioid_i + integer :: ni,no + integer :: ns_i, ns_o + integer :: n,l,k + integer , allocatable :: mask_i(:) + real(r8), allocatable :: frac_i(:) + real(r8), allocatable :: frac_o(:) + real(r8), allocatable :: ef_btr_i(:) ! input grid: EFs for broadleaf trees + real(r8), allocatable :: ef_fet_i(:) ! input grid: EFs for fineleaf evergreen + real(r8), allocatable :: ef_fdt_i(:) ! input grid: EFs for fineleaf deciduous + real(r8), allocatable :: ef_shr_i(:) ! input grid: EFs for shrubs + real(r8), allocatable :: ef_grs_i(:) ! input grid: EFs for grasses + real(r8), allocatable :: ef_crp_i(:) ! input grid: EFs for crops + real(r8), allocatable :: ef_btr_o(:) ! output grid: EFs for broadleaf trees + real(r8), allocatable :: ef_fet_o(:) ! output grid: EFs for fineleaf evergreen + real(r8), allocatable :: ef_fdt_o(:) ! output grid: EFs for fineleaf deciduous + real(r8), allocatable :: ef_shr_o(:) ! output grid: EFs for shrubs + real(r8), allocatable :: ef_grs_o(:) ! output grid: EFs for grasses + real(r8), allocatable :: ef_crp_o(:) ! output grid: EFs for crops + integer :: ier, rcode ! error status + real(r8) :: relerr = 0.00001_r8 ! max error: sum overlap wts ne 1 + character(len=*), parameter :: subname = 'mkvocef' + !----------------------------------------------------------------------- + + rc = ESMF_SUCCESS + call ESMF_VMLogMemInfo("At start of "//trim(subname)) + + if (root_task) then + write(ndiag,*) + write(ndiag,'(1x,80a1)') ('=',k=1,80) + write(ndiag,*) + write(ndiag,'(a)') 'Attempting to make VOC emission factors .....' + write(ndiag,'(a)') ' Input data file is '//trim(file_data_i) + write(ndiag,'(a)') ' Input mesh file is '//trim(file_mesh_i) + end if + + ! Open input data file + rcode = pio_openfile(pio_iosystem, pioid_i, pio_iotype, trim(file_data_i), pio_nowrite) + call ESMF_VMLogMemInfo("After pio_openfile "//trim(file_data_i)) + + ! Read in input mesh + mesh_i = ESMF_MeshCreate(filename=trim(file_mesh_i), fileformat=ESMF_FILEFORMAT_ESMFMESH, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After create mesh_i in "//trim(subname)) + + ! Determine ns_i + call ESMF_MeshGet(mesh_i, numOwnedElements=ns_i, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Determine ns_o + call ESMF_MeshGet(mesh_o, numOwnedElements=ns_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Allocate output variables + allocate (ef_btr_o(ns_o)) ; ef_btr_o(:) = 0._r8 + allocate (ef_fet_o(ns_o)) ; ef_fet_o(:) = 0._r8 + allocate (ef_fdt_o(ns_o)) ; ef_fdt_o(:) = 0._r8 + allocate (ef_shr_o(ns_o)) ; ef_shr_o(:) = 0._r8 + allocate (ef_grs_o(ns_o)) ; ef_grs_o(:) = 0._r8 + allocate (ef_crp_o(ns_o)) ; ef_crp_o(:) = 0._r8 + + ! Get the landmask from the input data file and reset the mesh mask based on that + allocate(frac_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort() + allocate(mask_i(ns_i), stat=ier) + if (ier/=0) call shr_sys_abort() + call mkpio_get_rawdata(pioid_i, 'LANDMASK', mesh_i, frac_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + do ni = 1,ns_i + if (frac_i(ni) > 0._r8) then + mask_i(ni) = 1 + else + mask_i(ni) = 0 + end if + end do + call ESMF_MeshSet(mesh_i, elementMask=mask_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! Create a route handle between the input and output mesh + allocate(frac_o(ns_o)) + call create_routehandle_r8(mesh_i=mesh_i, mesh_o=mesh_o, norm_by_fracs=.true., & + routehandle=routehandle, frac_o=frac_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_VMLogMemInfo("After create routehandle in "//trim(subname)) + + ! Read input Emission Factors + allocate (ef_btr_i(ns_i)) + if (ier/=0) call shr_sys_abort() + allocate (ef_fet_i(ns_i)) + if (ier/=0) call shr_sys_abort() + allocate (ef_fdt_i(ns_i)) + if (ier/=0) call shr_sys_abort() + allocate (ef_shr_i(ns_i)) + if (ier/=0) call shr_sys_abort() + allocate (ef_grs_i(ns_i)) + if (ier/=0) call shr_sys_abort() + allocate (ef_crp_i(ns_i)) + if (ier/=0) call shr_sys_abort() + + call mkpio_get_rawdata(pioid_i, 'ef_btr', mesh_i, ef_btr_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call mkpio_get_rawdata(pioid_i, 'ef_fet', mesh_i, ef_fet_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call mkpio_get_rawdata(pioid_i, 'ef_fdt', mesh_i, ef_fdt_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call mkpio_get_rawdata(pioid_i, 'ef_shr', mesh_i, ef_shr_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call mkpio_get_rawdata(pioid_i, 'ef_grs', mesh_i, ef_grs_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call mkpio_get_rawdata(pioid_i, 'ef_crp', mesh_i, ef_crp_i, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + + ! Regrid input data to model resolution + call regrid_rawdata(mesh_i, mesh_o, routehandle, ef_btr_i, ef_btr_o, rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call regrid_rawdata(mesh_i, mesh_o, routehandle, ef_fet_i, ef_fet_o, rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call regrid_rawdata(mesh_i, mesh_o, routehandle, ef_fdt_i, ef_fdt_o, rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call regrid_rawdata(mesh_i, mesh_o, routehandle, ef_shr_i, ef_shr_o, rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call regrid_rawdata(mesh_i, mesh_o, routehandle, ef_grs_i, ef_grs_o, rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call regrid_rawdata(mesh_i, mesh_o, routehandle, ef_crp_i, ef_crp_o, rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + ! Check for conservation + do no = 1, ns_o + if ( ef_btr_o(no) < 0._r8 ) then + write (6,*) 'MKVOCEF error: EF btr = ',ef_btr_o(no), ' is negative for no = ',no + call shr_sys_abort() + end if + if ( ef_fet_o(no) < 0._r8 ) then + write (6,*) 'MKVOCEF error: EF fet = ',ef_fet_o(no), ' is negative for no = ',no + call shr_sys_abort() + end if + if ( ef_fdt_o(no) < 0._r8 ) then + write (6,*) 'MKVOCEF error: EF fdt = ',ef_fdt_o(no), ' is negative for no = ',no + call shr_sys_abort() + end if + if ( ef_shr_o(no) < 0._r8 ) then + write (6,*) 'MKVOCEF error: EF shr = ',ef_shr_o(no), ' is negative for no = ',no + call shr_sys_abort() + end if + if ( ef_grs_o(no) < 0._r8 ) then + write (6,*) 'MKVOCEF error: EF grs = ',ef_grs_o(no), ' is negative for no = ',no + call shr_sys_abort() + end if + if ( ef_crp_o(no) < 0._r8 ) then + write (6,*) 'MKVOCEF error: EF crp = ',ef_crp_o(no), ' is negative for no = ',no + call shr_sys_abort() + end if + enddo + + + ! If have pole points on grid - set south pole to glacier + ! north pole is assumed as non-land + do no = 1,ns_o + if (abs((lat_o(no) - 90._r8)) < 1.e-6_r8) then + ef_btr_o(no) = 0._r8 + ef_fet_o(no) = 0._r8 + ef_fdt_o(no) = 0._r8 + ef_shr_o(no) = 0._r8 + ef_grs_o(no) = 0._r8 + ef_crp_o(no) = 0._r8 + end if + end do + + if (root_task) write(ndiag, '(a)') trim(subname)//" writing out voc emission factors" + call mkfile_output(pioid_o, mesh_o, 'EF1_BTR', ef_btr_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkfile_output') + call mkfile_output(pioid_o, mesh_o, 'EF1_FET', ef_fet_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkfile_output') + call mkfile_output(pioid_o, mesh_o, 'EF1_FDT', ef_fdt_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkfile_output') + call mkfile_output(pioid_o, mesh_o, 'EF1_SHR', ef_shr_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkfile_output') + call mkfile_output(pioid_o, mesh_o, 'EF1_GRS', ef_grs_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkfile_output') + call mkfile_output(pioid_o, mesh_o, 'EF1_CRP', ef_crp_o, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) call shr_sys_abort('error in calling mkfile_output') + call pio_syncfile(pioid_o) + + ! ----------------------------------------------------------------- + ! Wrap up + ! ----------------------------------------------------------------- + + ! Close the input file + call pio_closefile(pioid_i) + call ESMF_VMLogMemInfo("After pio_closefile in "//trim(subname)) + + ! Release memory + call ESMF_RouteHandleDestroy(routehandle, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + call ESMF_MeshDestroy(mesh_i, nogarbage = .true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) call shr_sys_abort() + call ESMF_VMLogMemInfo("After destroy operations in "//trim(subname)) + + if (root_task) then + write (ndiag,'(a)') 'Successfully made VOC Emission Factors' + end if + + end subroutine mkvocef + +end module mkvocefMod diff --git a/tools/mksurfdata_map/src/nanMod.F90 b/tools/mksurfdata_esmf/src/nanMod.F90 similarity index 100% rename from tools/mksurfdata_map/src/nanMod.F90 rename to tools/mksurfdata_esmf/src/nanMod.F90 diff --git a/tools/mksurfdata_map/src/shr_const_mod.F90 b/tools/mksurfdata_esmf/src/shr_const_mod.F90 similarity index 100% rename from tools/mksurfdata_map/src/shr_const_mod.F90 rename to tools/mksurfdata_esmf/src/shr_const_mod.F90 diff --git a/tools/mksurfdata_map/src/shr_kind_mod.F90 b/tools/mksurfdata_esmf/src/shr_kind_mod.F90 similarity index 92% rename from tools/mksurfdata_map/src/shr_kind_mod.F90 rename to tools/mksurfdata_esmf/src/shr_kind_mod.F90 index d1219223da..74f6d18b07 100644 --- a/tools/mksurfdata_map/src/shr_kind_mod.F90 +++ b/tools/mksurfdata_esmf/src/shr_kind_mod.F90 @@ -11,6 +11,7 @@ MODULE shr_kind_mod integer,parameter :: SHR_KIND_RN = kind(1.0) ! native real integer,parameter :: SHR_KIND_I8 = selected_int_kind (13) ! 8 byte integer integer,parameter :: SHR_KIND_I4 = selected_int_kind ( 6) ! 4 byte integer + integer,parameter :: SHR_KIND_I2 = selected_int_kind ( 4) ! 2 byte integer integer,parameter :: SHR_KIND_IN = kind(1) ! native integer integer,parameter :: SHR_KIND_CS = 80 ! short char integer,parameter :: SHR_KIND_CL = 256 ! long char diff --git a/tools/mksurfdata_esmf/src/shr_string_mod.F90 b/tools/mksurfdata_esmf/src/shr_string_mod.F90 new file mode 100644 index 0000000000..089eb21a19 --- /dev/null +++ b/tools/mksurfdata_esmf/src/shr_string_mod.F90 @@ -0,0 +1,142 @@ +module shr_string_mod + + implicit none + private + + public :: shr_string_countChar ! Count number of char in string, fn + public :: shr_string_endIndex ! Index of end of substr in str + public :: shr_string_betweenTags ! get the substring between the two tags + +!=============================================================================== +contains +!=============================================================================== + + integer function shr_string_countChar(str,char,rc) + + ! count number of occurances of a single character in a string + + ! !INPUT/OUTPUT PARAMETERS: + character(len=*) ,intent(in) :: str ! string to search + character(1) ,intent(in) :: char ! char to search for + integer,intent(out),optional :: rc ! return code + + !----- local ----- + integer :: count ! counts occurances of char + integer :: n ! generic index + integer :: t01 = 0 ! timer + + !----- formats ----- + character(*),parameter :: subName = "(shr_string_countChar) " + character(*),parameter :: F00 = "('(shr_string_countChar) ',4a)" + + !------------------------------------------------------------------------------- + ! Notes: + !------------------------------------------------------------------------------- + + count = 0 + do n = 1, len_trim(str) + if (str(n:n) == char) count = count + 1 + end do + shr_string_countChar = count + + if (present(rc)) rc = 0 + + end function shr_string_countChar + + !=============================================================================== + subroutine shr_string_betweenTags(string,startTag,endTag,substr,rc) + + ! Get the substring found between the start and end tags. + + ! !INPUT/OUTPUT PARAMETERS: + character(*) ,intent(in) :: string ! string to search + character(*) ,intent(in) :: startTag ! start tag + character(*) ,intent(in) :: endTag ! end tag + character(*) ,intent(out) :: substr ! sub-string between tags + integer,intent(out),optional :: rc ! retrun code + + !--- local --- + integer :: iStart ! substring start index + integer :: iEnd ! substring end index + integer :: rCode ! return code + integer :: t01 = 0 ! timer + character(*),parameter :: F00 = "('(shr_string_betweenTags) ',4a)" + + !------------------------------------------------------------------------------- + ! Notes: + ! * assumes the leading/trailing white space is not part of start & end tags + !------------------------------------------------------------------------------- + + iStart = shr_string_endIndex(string,trim(adjustL(startTag))) ! end of start tag + iEnd = index(string,trim(adjustL(endTag ))) ! start of end tag + + rCode = 0 + substr = "" + + if (iStart < 1) then + write(6,F00) "ERROR: can't find start tag in string" + write(6,F00) "ERROR: start tag = ",trim(startTag) + write(6,F00) "ERROR: string = ",trim(string) + rCode = 1 + else if (iEnd < 1) then + write(6,F00) "ERROR: can't find end tag in string" + write(6,F00) "ERROR: end tag = ",trim( endTag) + write(6,F00) "ERROR: string = ",trim(string) + rCode = 2 + else if ( iEnd <= iStart) then + write(6,F00) "ERROR: start tag not before end tag" + write(6,F00) "ERROR: start tag = ",trim(startTag) + write(6,F00) "ERROR: end tag = ",trim( endTag) + write(6,F00) "ERROR: string = ",trim(string) + rCode = 3 + else if ( iStart+1 == iEnd ) then + substr = "" + write(6,F00) "WARNING: zero-length substring found in ",trim(string) + else + substr = string(iStart+1:iEnd-1) + if (len_trim(substr) == 0 ) then + write(6,F00) "WARNING: white-space substring found in ",trim(string) + end if + end if + + if (present(rc)) rc = rCode + + end subroutine shr_string_betweenTags + + !=============================================================================== + integer function shr_string_endIndex(string,substr,rc) + + ! Get the ending index of substr within string + + ! !INPUT/OUTPUT PARAMETERS: + character(len=*) ,intent(in) :: string ! string to search + character(len=*) ,intent(in) :: substr ! sub-string to search for + integer ,intent(out),optional :: rc ! return code + + !--- local --- + integer :: i ! generic index + !------------------------------------------------------------------------------- + ! Notes: + ! * returns zero if substring not found, uses len_trim() intrinsic + ! * very similar to: i = index(str,substr,back=.true.) + ! * do we need this function? + !------------------------------------------------------------------------------- + + i = index(trim(string),trim(substr)) + if ( i == 0 ) then + shr_string_endIndex = 0 ! substr is not in string + else + shr_string_endIndex = i + len_trim(substr) - 1 + end if + + ! ------------------------------------------------------------------- + ! i = index(trim(string),trim(substr),back=.true.) + ! if (i == len(string)+1) i = 0 + ! shr_string_endIndex = i + ! ------------------------------------------------------------------- + + if (present(rc)) rc = 0 + + end function shr_string_endIndex + +end module shr_string_mod diff --git a/tools/mksurfdata_esmf/src/shr_sys_mod.F90 b/tools/mksurfdata_esmf/src/shr_sys_mod.F90 new file mode 100644 index 0000000000..ef5ca5f566 --- /dev/null +++ b/tools/mksurfdata_esmf/src/shr_sys_mod.F90 @@ -0,0 +1,51 @@ +module shr_sys_mod + + use shr_kind_mod ! defines real & integer kinds + + implicit none + private + +#include + + public :: shr_sys_abort ! abort a program + +!=============================================================================== +CONTAINS +!=============================================================================== + + subroutine shr_sys_abort(message, file, line) + + ! Parallel emergency stop + + ! input/output variables + character(len=*), optional, intent(in) :: message + character(len=*), optional, intent(in) :: file + integer, optional, intent(in) :: line + + ! Local variables + integer :: rc + integer :: ier + character(len=SHR_KIND_CL):: abort_msg + + if (.not. present(message)) then + rc = 1001 + call mpi_abort(MPI_COMM_WORLD, rc, ier) + else + if (present(file) .and. present(line)) then + write(abort_msg, '(4a,i0)') trim(message),' at ',trim(file),':',line + else if (present(file)) then + write(abort_msg, '(3a)') trim(message),' at ',trim(file) + else if (present(line)) then + write(abort_msg, '(2a,i0)') trim(message),' on line ',line + else + write(abort_msg, '(a)') trim(message) + end if + + write(6,*) trim(message) + rc = 1001 + call mpi_abort(MPI_COMM_WORLD, rc, ier) + end if + + end subroutine shr_sys_abort + +end module shr_sys_mod diff --git a/tools/mksurfdata_map/Makefile.data b/tools/mksurfdata_map/Makefile.data deleted file mode 100644 index 1609b35a75..0000000000 --- a/tools/mksurfdata_map/Makefile.data +++ /dev/null @@ -1,310 +0,0 @@ -# -*- mode:Makefile -*- -# -# To generate all surface data sets, run: -# make -f Makefile.data all -# -# To generate a single dataset, run make with the name of the rule you -# want to build. For example, to generate the crop data set for 1x1_numaIA: -# -# make -f Makefile.data crop-numa -# -# NOTE: The default behavior is to parallelize data set creation using -# the batch system by submitting jobs to the batch queue (on cheyenne). -# On yellowstone we submit to an interactive queue in the -# background. Standard out and standard error are redirected to a text -# file. To change this behavior, you can comment out the BATCHJOBS and -# BACKGROUND variables and replace them with empty variables. -# -# WARNING: Do not put more than one mksurfdata call per rule. output -# redirection is based on the rule name, and multiple rules will over -# write the previous output or incomprehensively merge output from -# simultaneously running jobs. -# -# Note that we typically use -no_surfdata in rules for transient files, having -# separate rules to make the year-1850 and year-2000 surface datasets. This -# results in extra processes, but ensures that the surface datasets have the -# correct name (rather than having 'hist' or 'rcpXXX' in their file name). -# - -# Set up special characters -null := - -# Set a few things needed for batch handling -PROJECT = $(shell cat $(HOME)/.cesm_proj) -LOGOUT = $@.stdout.txt -PWD = $(shell pwd) - -# Setup batch handling for either cheyenne or yellowstone -# Determine what to use by machine hostname -BATCHJOBS_ys = execgy -# Send to regular queue for 2 processors with extra memory, combine stdout/stderr output to log file, and send email on abort or exit -BATCHJOBS_ch = qsub -A $(PROJECT) -q regular -l select=1:ncpus=2:mem=110GB -l walltime=4:00:00 -j oe -N $(LOGOUT) -m ae -- -HOST = $(shell hostname) -FINDCH = $(findstring cheyenne,$(HOST)) -ifeq ($(FINDCH),$(null)) - ifeq ($(PROJECT),$(null)) - $(error Can NOT find PROJECT number from ~/.cesm_proj file create it and try again) - endif - BATCHJOBS = $(BATCHJOBS_ys) - BACKGROUND = &> $(LOGOUT) & -else - BATCHJOBS = $(BATCHJOBS_ch) - BACKGROUND = -rundir $(PWD) -endif - -MKSURFDATA = $(BATCHJOBS) $(PWD)/mksurfdata.pl -SUBSETDATA = $(PWD)/../site_and_regional/subset_data -MODIFYSURF = $(PWD)/../modify_input_files/fsurdat_modifier --overwrite - -CDATE = $(shell date +%y%m%d) - -# subset_data options -# -SUBSETDATA_POINT = $(SUBSETDATA) point --silent --overwrite --uniform-snowpack --cap-saturation --crop --outdir . -SUBSETDATA_POINT_ALLLU = $(SUBSETDATA_POINT) --include-nonveg -SUBSETDATA_POINT_URBAN = $(SUBSETDATA_POINT) --include-nonveg - -# Subset data sites... -SUBSETDATA_1X1_BRAZIL := --lat -7 --lon -55 --site 1x1_brazil -SUBSETDATA_1X1_NUMAIA := --lat 40.6878 --lon 267.0228 --site 1x1_numaIA -SUBSETDATA_1X1_SMALL := --lat 40.6878 --lon 267.0228 --site 1x1_smallvilleIA \ - --dompft 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 \ - --pctpft 6.5 1.5 1.6 1.7 1.8 1.9 1.5 1.6 1.7 1.8 1.9 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 1.5 -# NOTE: The 1850 smallvilleIA site is constructed to start with 100% natural vegetation, so we can test transition to crops -SUBSETDATA_1X1_SMALL1850 := --lat 40.6878 --lon 267.0228 --site 1x1_smallvilleIA --dompft 13 --pctpft 100 - -SUBSETDATA_1X1_MEXICOCITY := --lat 19.5 --lon 260.5 --site 1x1_mexicocityMEX --out-surface surfdata_1x1_mexicocityMEX_hist_78pfts_CMIP6_simyr2000.nc -SUBSETDATA_1X1_VANCOUVER := --lat 49.5 --lon 236.5 --site 1x1_vancouverCAN --out-surface surfdata_1x1_vancouverCAN_hist_78pfts_CMIP6_simyr2000.nc -SUBSETDATA_1X1_URBALPHA := --lat -37.7308 --lon 0 --site 1x1_urbanc_alpha --out-surface surfdata_1x1_urbanc_alpha_hist_78pfts_CMIP6_simyr2000.nc -# f19 and f09 are standard resolutions, f10 is used for testing, f45 is used for FATES -# ne30np4 is standard resolution for SE dycore in CAM, C96 is standard for fv3 dycore -# The ne30np4 series (including pg2, pg3, pg4) are standard for SE dycore -# The variable resolution grids for ARCTIC, ARCTICGRIS and CONUS are also standard -STANDARD_RES_NO_CROP = 0.9x1.25,1.9x2.5,10x15 -STANDARD_RES = 0.9x1.25,1.9x2.5,10x15,4x5,ne30np4,C96,ne30pg2,ne30pg3,ne30pg4,ne120np4pg3,ne0np4ARCTICGRISne30x8,ne0np4ARCTICne30x4,ne0np4CONUSne30x8,ne3np4.pg3,ne5np4.pg3,ne16np4.pg3,mpasa480,mpasa120 - -# For future CMIP6 scenarios: SSP-RCP's -FUTURE_RES = 0.9x1.25,1.9x2.5,10x15 -# For historical transient cases (TRY TO KEEP THIS LIST AS SHORT AS POSSIBLE) -TRANS_RES = 0.9x1.25,1.9x2.5,10x15,ne30np4,ne0np4ARCTICGRISne30x8,ne0np4ARCTICne30x4,ne0np4CONUSne30x8 - -# ne120np4 is for high resolution SE dycore, ne16 is for testing SE dycore -# T42 is for SCAM -# f05 is needed for running full chemistry model -# nldas is for NWP working with WRF -STANDARD = \ - global-present \ - global-present-nldas \ - global-present-T42 - -TROPICS = \ - crop-tropics-present \ - crop-tropics-historical \ - crop-tropics-transient - -CROP = \ - crop-global-present \ - crop-global-present-ne16np4 \ - crop-global-present-ne120np4 \ - crop-numa-present \ - crop-numa-historical \ - crop-smallville \ - crop-smallville-historical \ - crop-global-historical \ - crop-global-transient \ - crop-global-future -all : standard tropics crop urban landuse-timeseries - -all-subset : \ - 1x1_brazil-tropics-present \ - crop-tropics-historical \ - crop-tropics-transient \ - crop-numa-present \ - crop-numa-historical \ - crop-smallville \ - crop-smallville-historical \ - urban-present urban-alpha - -DEBUG: - @echo "HOST := $(HOST)" - @echo "PROJECT := $(PROJECT)" - @echo "BATCHJOBS := $(BATCHJOBS)" - @echo "BACKGROUND := $(BACKGROUND)" - -# -# standard -# -standard : $(STANDARD) - -global-present : FORCE - $(MKSURFDATA) -no-crop -vic -glc_nec 10 -y 2000 -res $(STANDARD_RES_NO_CROP) $(BACKGROUND) - -# T42 is needed for SCAM -global-present-T42 : FORCE - $(MKSURFDATA) -no-crop -glc_nec 10 -y 2000 -res 64x128 $(BACKGROUND) - -global-present-nldas : FORCE - $(MKSURFDATA) -no-crop -hirespft -glc_nec 10 -y 2005 -res 0.125nldas2 $(BACKGROUND) - -# -# tropics -# -tropics : $(TROPICS) - -crop-tropics-present : brazil-tropics-present - $(MKSURFDATA) -glc_nec 10 -y 2000 -res 5x5_amazon $(BACKGROUND) - -1x1_brazil-tropics-present : FORCE - $(SUBSETDATA_POINT_ALLLU) --create-surface $(SUBSETDATA_1X1_BRAZIL) - - -crop-tropics-historical : FORCE - $(SUBSETDATA_POINT_ALLLU) --create-surface $(SUBSETDATA_1X1_BRAZIL) --cfg-file default_data_1850.cfg - -crop-tropics-transient : FORCE - $(SUBSETDATA_POINT_ALLLU) --create-landuse $(SUBSETDATA_1X1_BRAZIL) - -# -# crop -# -crop : $(CROP) - -crop-global-present : FORCE - $(MKSURFDATA) -glc_nec 10 -y 2000 -r $(STANDARD_RES) $(BACKGROUND) - -crop-global-present-0.125 : FORCE - $(MKSURFDATA) -hirespft -glc_nec 10 -y 2000 -r 0.125x0.125 $(BACKGROUND) - -crop-global-present-f05 : FORCE - $(MKSURFDATA) -glc_nec 10 -y 1850,2000 -res 0.47x0.63 $(BACKGROUND) - -crop-numa-present : FORCE - $(SUBSETDATA_POINT_ALLLU) --create-surface $(SUBSETDATA_1X1_NUMAIA) - -crop-numa-historical : FORCE - $(SUBSETDATA_POINT_ALLLU) --create-surface $(SUBSETDATA_1X1_NUMAIA) --cfg-file default_data_1850.cfg - -crop-smallville : FORCE - $(SUBSETDATA_POINT) --create-surface $(SUBSETDATA_1X1_SMALL) - -crop-global-present-ne16np4 : FORCE - $(MKSURFDATA) -glc_nec 10 -y 2000 -res ne16np4 $(BACKGROUND) - -crop-global-present-ne120np4 : FORCE - $(MKSURFDATA) -glc_nec 10 -y 2000 -res ne120np4 $(BACKGROUND) - -# Note that the smallville 1850 dataset is entirely natural vegetation. This -# facilitates testing a transient case that starts with no crop, and then later -# adds crop (to make sure that it works properly to add crop in a grid cell -# where there used to be no crop). -crop-smallville-historical : FORCE - $(SUBSETDATA_POINT) --create-surface $(SUBSETDATA_1X1_SMALL1850) --cfg-file default_data_1850.cfg - -# Setup the historical case for SSP5-8.5 so that historical can be used to go into the future. -crop-global-historical : FORCE - $(MKSURFDATA) -glc_nec 10 -y 1850 -ssp_rcp SSP5-8.5 -res $(STANDARD_RES) $(BACKGROUND) - -crop-global-historical-f05 : FORCE - $(MKSURFDATA) -glc_nec 10 -y 1850 -r 0.47x0.63 $(BACKGROUND) - -crop-global-historical-ne120np4 : FORCE - $(MKSURFDATA) -glc_nec 10 -y 1850 -res ne120np4 $(BACKGROUND) - -crop-global-transient: FORCE - $(MKSURFDATA) -no_surfdata -glc_nec 10 -y 1850-2000 -res $(TRANS_RES) $(BACKGROUND) - -crop-global-transient-ne120np4 : FORCE - $(MKSURFDATA) -no_surfdata -glc_nec 10 -y 1850-2000 -res ne120np4 $(BACKGROUND) - -crop-global-transient-f05 : FORCE - $(MKSURFDATA) -no_surfdata -glc_nec 10 -y 1850-2000 -res 0.47x0.63 $(BACKGROUND) - -# -# Crop with future scenarios -# -crop-global-future : crop-global-SSP1-2.6 crop-global-SSP3-7.0 crop-global-SSP5-3.4 crop-global-SSP2-4.5 \ - crop-global-SSP1-1.9 crop-global-SSP4-3.4 crop-global-SSP4-6.0 crop-global-SSP5-8.5 - -crop-global-SSP1-2.6 : FORCE - $(MKSURFDATA) -no_surfdata -glc_nec 10 -y 1850-2100 \ - -ssp_rcp SSP1-2.6 -res $(FUTURE_RES) $(BACKGROUND) - -crop-global-SSP3-7.0 : FORCE - $(MKSURFDATA) -no_surfdata -glc_nec 10 -y 1850-2100 \ - -ssp_rcp SSP3-7.0 -res $(FUTURE_RES) $(BACKGROUND) - -crop-global-SSP5-3.4 : FORCE - $(MKSURFDATA) -no_surfdata -glc_nec 10 -y 1850-2100 \ - -ssp_rcp SSP5-3.4 -res $(FUTURE_RES) $(BACKGROUND) - -crop-global-SSP2-4.5 : FORCE - $(MKSURFDATA) -no_surfdata -glc_nec 10 -y 1850-2100 \ - -ssp_rcp SSP2-4.5 -res $(FUTURE_RES) $(BACKGROUND) - -crop-global-SSP1-1.9 : FORCE - $(MKSURFDATA) -no_surfdata -glc_nec 10 -y 1850-2100 \ - -ssp_rcp SSP1-1.9 -res $(FUTURE_RES) $(BACKGROUND) - -crop-global-SSP4-3.4 : FORCE - $(MKSURFDATA) -no_surfdata -glc_nec 10 -y 1850-2100 \ - -ssp_rcp SSP4-3.4 -res $(FUTURE_RES) $(BACKGROUND) - -crop-global-SSP4-6.0 : FORCE - $(MKSURFDATA) -no_surfdata -glc_nec 10 -y 1850-2100 \ - -ssp_rcp SSP4-6.0 -res $(FUTURE_RES) $(BACKGROUND) - -crop-global-SSP5-8.5 : FORCE - $(MKSURFDATA) -no_surfdata -glc_nec 10 -y 1850-2100 \ - -ssp_rcp SSP5-8.5 -res $(FUTURE_RES) $(BACKGROUND) - -# -# urban -# -urban : urban-present urban-alpha - -urban-present : mexicocity vancouver - -mexicocity : FORCE - $(SUBSETDATA_POINT_URBAN) --create-surface $(SUBSETDATA_1X1_MEXICOCITY) - $(MODIFYSURF) modify_1x1_mexicocityMEX.cfg -i surfdata_1x1_mexicocityMEX_hist_78pfts_CMIP6_simyr2000.nc -o surfdata_1x1_mexicocityMEX_hist_78pfts_CMIP6_simyr2000_c$(CDATE).nc - $(RM) surfdata_1x1_mexicocityMEX_hist_78pfts_CMIP6_simyr2000.nc - -vancouver : FORCE - $(SUBSETDATA_POINT_URBAN) --create-surface $(SUBSETDATA_1X1_VANCOUVER) - $(MODIFYSURF) modify_1x1_vancouverCAN.cfg -i surfdata_1x1_vancouverCAN_hist_78pfts_CMIP6_simyr2000.nc -o surfdata_1x1_vancouverCAN_hist_78pfts_CMIP6_simyr2000_c$(CDATE).nc - $(RM) surfdata_1x1_vancouverCAN_hist_78pfts_CMIP6_simyr2000.nc - -# NOTE(bja, 2015-01) skip abort on invalid data necessary as of 2015-01. See -# /glade/p/cesm/cseg/inputdata/lnd/clm2/surfdata_map/README_c141219 -urban-alpha : FORCE - $(SUBSETDATA_POINT_URBAN) --create-surface $(SUBSETDATA_1X1_URBALPHA) - $(MODIFYSURF) modify_1x1_urbanc_alpha.cfg -i surfdata_1x1_urbanc_alpha_hist_78pfts_CMIP6_simyr2000.nc -o surfdata_1x1_urbanc_alpha_hist_78pfts_CMIP6_simyr2000_c$(CDATE).nc - $(RM) surfdata_1x1_urbanc_alpha_hist_78pfts_CMIP6_simyr2000.nc - -# -# landuse timeseries -# -landuse-timeseries : landuse-timeseries-smallville - -# NOTE: TODO: This needs to be chagned to use subset_data when transient configurations are resolved (see Issue #1673 -landuse-timeseries-smallville : FORCE - $(MKSURFDATA) -no_surfdata -glc_nec 10 -y 1850-1855 -r 1x1_smallvilleIA \ - -pft_idx 17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78 \ - -pft_frc 6.5,1.5,1.6,1.7,1.8,1.9,1.5,1.6,1.7,1.8,1.9,1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5 \ - -dynpft single_point_dynpft_files/landuse_timeseries_smallvilleIA_hist_simyr1850-1855.txt \ - $(BACKGROUND) - -# -# clean up the working directory by removing generated files -# -clean : FORCE - -rm *~ - -clobber : clean - -rm surfdata_*.nc surfdata_*.log surfdata_*.namelist - -# -# generic rule to force things to happen -# -FORCE : - diff --git a/tools/mksurfdata_map/README b/tools/mksurfdata_map/README deleted file mode 100644 index bd324580bb..0000000000 --- a/tools/mksurfdata_map/README +++ /dev/null @@ -1,73 +0,0 @@ -$CTSMROOT/tools/mksurfdata_map/README Jun 08, 2018 - -The routines in this directory create a surface dataset. -The output grid is read in from the input namelist and -can correspond to either a global or regional grid. - -Supported model resolutions are those found in the repository input data directory - $DIN_LOC_ROOT/lnd/clm2/mappingdata/maps - -Surface datasets can either be created for two separate cases - a) for supported model resolutions - b) for unsupported (user-specified) model resolutions - -The following steps provide a method to create the executable -and generate the surface dataset: - -1) Make the mksurfdata_map executable - - Starting from this directory $CTSMROOT/tools/mksurfdata_map - > cd src - > gmake - By default code compiles optimized so it's reasonably fast. If you want - to use the debugger, with bounds-checking, and float trapping on do the - following: - gmake OPT=FALSE - See Also: See the $CTSMROOT/tools/README file for notes about setting - the path for NetCDF and running with shared-memory parallelism. - -2) For supported model resolutions - skip this step - - For unsupported model resolutions - do the following... - determine the pathname of the model resolution SCRIP grid file - - Starting from this directory $CTSMROOT/tools/mksurfdata_map - > cd ../mkmapdata - invoke one of the following commands - (for global resolution) - > ./mkmapdata.sh -f -res -type global - (for regional resolution) - > ./mkmapdata.sh -f -res -type regional - > cd ../ - - note: the mapping files generated in ./mkmapdata will be used to - generate the surface dataset - note: the res argument above () MUST be identical to the one provided to - mksurfdata.pl (see below) - -3) make surface dataset(s) - - Starting from this directory $CTSMROOT/tools/mksurfdata_map - > mksurfdata.pl --help (for full usage instructions) - For supported model resolution () - > mksurfdata.pl -res [options] - - For supported model resolutions for SSP scenarios - > mksurfdata.pl -res -ssp_rcp -years 1850-2100 - - For unsupported, user specified model resolutions - > mksurfdata.pl -res usrspec -usr_gname -usr_gdate - - Note that the argument to usr_gname MUST be the same as the -res argument value - when invoking mkmapdata - - Example, for gridname=1x1_boulderCO with maps created on Jan/13/2012 - - > mksurfdata.pl -res usrspec -usr_gname 1x_boulderCO -usr_gdate 20120113 - -Lists of input files for range of dates historical or future scenarios: - - landuse_timeseries_hist_16pfts_simyr1850-2015.txt --- List of historical input PFT files from 1850 to 2015 - -(Historical period from 1850-2015 datafiles all point to the historical files) - diff --git a/tools/mksurfdata_map/README.developers b/tools/mksurfdata_map/README.developers deleted file mode 100644 index 6513aeb131..0000000000 --- a/tools/mksurfdata_map/README.developers +++ /dev/null @@ -1,227 +0,0 @@ -$CTSMROOT/tools/mksurfdata_map/README.developers Jun/08/2018 - -============================================================================ -============================================================================ -Developer's guide for mksurfdata_map -============================================================================ -============================================================================ - -============================================================================ -Table of Contents -============================================================================ - -I. Adding a new raw data file - -II. Adding mapping files for a raw data file with a new grid / landmask - -III. Checks that should be done when making new surface datasets - -============================================================================ -I. Adding a new raw data file -============================================================================ - -Here is what you need to change when adding a new raw data file, with one or -more fields that need to be remapped to the CLM resolution. Note that -additional steps are needed (beyond what's listed here) when the field -you're adding specifies something about the subgrid breakdown (into -landunits, columns & pfts): for those fields, additional code is needed to -ensure that percentages add to 100%. - -Note: The following assumes that the new file uses an existing set of -mapping files, or that you have already done everything necessary to add a -new set of mapping files. If your raw data file has a new grid, or a new -landmask on an existing grid, see the instructions for adding mapping files -in a separate section of this document. - -- Add a new module in $CTSMROOT/tools/mksurfdata_map/src that provides a routine for - remapping your new field(s). - - Note that there is generally one module per input file; multiple fields - can be regridded using a single subroutine or multiple subroutines. - -- Add your new file in $CTSMROOT/tools/mksurfdata_map/src/Srcfiles - -- Add new namelist options in $CTSMROOT/tools/mksurfdata_map/src/mkvarctl.F90; e.g., for a - new field xxx: - - mksrf_fxxx - - map_fxxx - -- Add output calls in $CTSMROOT/tools/mksurfdata_map/src/mkfileMod.F90; you need to add - calls in 3 places: - - raw data file name attribute (nf_put_att_text call) - - mapping file name attribute (nf_put_att_text call) - - variable definition (ncd_defvar calls) - Make sure this goes in an 'if (.not dynlanduse)' conditional, if - appropriate - -- Add code in $CTSMROOT/tools/mksurfdata_map/src/mksurfdat.F90; you need to add the - following: - - add a 'use' statement to use your new regridding routine(s) - - declare array(s) to hold data on the output grid - - add your new mksrf_fxxx and map_fxxx variables to the 'namelist - /clmexp/' declaration - - document your new mksrf_fxxx and map_fxxx variables in the long - comment following the 'namelist /clmexp/' declaration - - add your new array(s) to the allocation statement under the heading - "Allocate and initialize dynamic memory" - - initialize your new array(s) in the initialization section following - the allocation - - add output to ndiag (the log file) documenting your new mksrf_fxxx and - map_fxxx variables - - add call(s) to your new subroutine(s) for regridding the data - - add calls to nf_inq_varid & nf_put_var_double (or nf_put_var_int) for - each new output variable; make sure to put these calls in the section - for dynlanduse = false and/or true, as appropriate - - add a deallocation statement for each new output variable - -- Add your new file in $CTSMROOT/bld/namelist_files/namelist_definition_ctsm.xml; - e.g. (replace xxx with your new field): - - - XXX dataset for mksurfdata - - -- Add your new mksrf_fxxx variable to the list of valid_values for - mksrf_filename in $CTSMROOT/bld/namelist_files/namelist_definition_ctsm.xml - -- Add defaults in $CTSMROOT/bld/namelist_files/namelist_defaults_ctsm_tools.xml; - note that the "type" attribute is a short code that can be used in - mksurfdata.pl, and doesn't have to match the "xxx" that is used elsewhere - - lmask - - hgrid - - mksrf_filename - - mksrf_fxxx (including hgrid and lmask attributes) - -- Add hooks to your new files in $CTSMROOT/tools/mksurfdata_map/mksurfdata.pl: - - add new string in the list following 'foreach my $typ' - - add the new mapping file to clmexp, as in: - map_fxxx = '$map{'xxx'}' - - add the new raw data file to clmexp, as in: - mksrf_fxxx = '$datfil{'xxx'}' - -- Add new raw data file to the inputdata repository: lnd/clm2/rawdata - - locally - - check in to the inputdata svn repository - -- Add documentation for your new mksrf_fxxx in $CTSMROOT/doc/UsersGuide/tools.xml - -============================================================================ -II. Adding mapping files for a raw data file with a new grid / landmask -============================================================================ - -If your raw data file is on a new grid, or just has a new landmask on an -existing grid, you will need to perform a number of additional steps, as -laid out here. - -- First, move your data file to the inputdata directory and give it its - final name. (This will ensure that the appropriate metadata is put in the - SCRIP grid file.) - -- Make a scrip grid file from your data file using mkmapgrids, and move it - to the inputdata directory - -- Add a scripgriddata entry for the new scrip grid file in - $CTSMROOT/bld/namelist_files/namelist_defaults_ctsm_tools.xml - -- If necessary, add other entries in - $CTSMROOT/bld/namelist_files/namelist_defaults_ctsm_tools.xml giving information about your - scrip grid file: - - If this is a high resolution grid (e.g., 3min or higher), add a - scripgriddata_lrgfile_needed entry, saying we need 64bit_offset - (or netcdf4) support for mapping files made with this scrip grid - file - - If the grid file is in UGRID format rather than SCRIP grid - format, add scripgriddata_type and scripgriddata_meshname - entries. If you don't know what I'm talking about, then your - grid file is in SCRIP format and you can ignore this. - -- If necessary, add new grid and/or landmask to lists of valid values for - hgrid, res and lmask in $CTSMROOT/bld/namelist_files/namelist_definition_ctsm.xml - - Note that a new resolution currently needs to be added to both the hgrid - and res lists of valid values, although in the future this - should probably be changed so that these raw data grids just - appear in hgrid - -- Add the new grid-landmask combo to the 'mapgrids' list in - $CTSMROOT/bld/namelist_files/checkmapfiles.ncl - -- Add the new grid-landmask combo to the 'grids' list in - $CTSMROOT/tools/shared/mkmapdata/mkmapdata.sh (in the clm4_5 branch of the - conditional) - -- Make mapping files, from $CTSMROOT/tools/shared/mkmapdata - - Modify mkmapdata.sh: - - edit the grids list so it only contains your new grid - - Modify regridbatch.sh as desired, e.g.: - - project number - - number of processors (BSUB -n line, span, and the regrid_num_proc setting) - - wall-clock limit - - if ESMFBIN_PATH is in your environment, you may want to unset it; - this can be important to allow mkmapdata.sh choose a different - executable for mpi vs serial runs - - if you renamed the mkmapdata.sh script, be sure to call the - renamed script at the bottom of regridbatch.sh - - Submit regridbatch.sh - -- When mapping files have all been created, run createXMLEntries.pl from - $CTSMROOT/tools/shared/mkmapdata (usage: just run the script with no arguments) - -- Cut and paste the xml entries from mapping_entries.txt (created by - createXMLEntries.pl) into $CTSMROOT/bld/namelist_files/namelist_defaults_ctsm.xml, - in the correct locations - -- Move mapping files to correct location, either using mv_cmds.sh created by - createXMLEntries.pl, or using $CTSMROOT/tools/shared/mkmapdata/mvNimport.sh. - - Note that the latter also imports to the inputdata directory; if you - don't use that, you'll need to add the files to the inputdata - directory yourself - - -============================================================================ -III. Checks that should be done when making new surface datasets -============================================================================ - -Remaking all surface datasets carries the risk of introducing unintended -changes, particularly when you are expecting answer changes (so you -don't notice unintended answer changes that are mixed with the expected -changes). - -Here are some things to check after making a new set of surface -datasets: - -- For at least one global dataset (probably a production resolution - rather than a low resolution that is just used for testing): Compare - the new dataset against the previous version: - - - Compare header (via ncdump -h) and/or log file: ensure that the same - source data were used, except where you expect differences - - - Compare all fields with a tool like cprnc: make sure that the only - fields that differ are those you expect to differ - - - Visually compare all fields that differ: make sure differences look - reasonable and as expected - -And here are some things to check for when making new landuse.timeseries -datasets (which often happens at the same time, and most of the above applies -as well): - -- Compare one of the production resolution datasets to a previous version. - - - If part of it should be identical (for example the historical period) make - sure it is identical as expected (using cprnc make sure the historical period - is identical and only the future scenario changes). - - - If the historical period should be identical, make sure the 1850 surface dataset - created is identical to the previous one. - - - Visually compare all fields/times that differ: make sure differences look - reasonable and as expected. Go through at least the first and last time to see - that the change in time is as expected. - - - Quickly going through the time differences for at least one field that changes - can also be useful to see that there isn't a sudden jump for a particular time. - - - Go through the list of raw PFT files that were used to create the dataset and make - sure it appears to be correct (ncdump -v input_pftdata_filename) diff --git a/tools/mksurfdata_map/default_data_1850.cfg b/tools/mksurfdata_map/default_data_1850.cfg deleted file mode 100644 index 311aeef13d..0000000000 --- a/tools/mksurfdata_map/default_data_1850.cfg +++ /dev/null @@ -1,29 +0,0 @@ -[main] -clmforcingindir = /glade/p/cesmdata/inputdata - -[datm_gswp3] -dir = /glade/p/cgd/tss/CTSM_datm_forcing_data/atm_forcing.datm7.GSWP3.0.5d.v1.c170516 -domain = domain.lnd.360x720_gswp3.0v1.c170606.nc -solardir = Solar -precdir = Precip -tpqwdir = TPHWL -solartag = clmforc.GSWP3.c2011.0.5x0.5.Solr. -prectag = clmforc.GSWP3.c2011.0.5x0.5.Prec. -tpqwtag = clmforc.GSWP3.c2011.0.5x0.5.TPQWL. -solarname = CLMGSWP3v1.Solar -precname = CLMGSWP3v1.Precip -tpqwname = CLMGSWP3v1.TPQW - -[surfdat] -dir = lnd/clm2/surfdata_map/release-clm5.0.18 -surfdat_16pft = surfdata_0.9x1.25_hist_16pfts_Irrig_CMIP6_simyr1850_c190214.nc -surfdat_78pft = surfdata_0.9x1.25_hist_78pfts_CMIP6_simyr1850_c190214.nc - -[landuse] -dir = lnd/clm2/surfdata_map/release-clm5.0.18 -landuse_16pft = landuse.timeseries_0.9x1.25_hist_16pfts_Irrig_CMIP6_simyr1850-2015_c190214.nc -landuse_78pft = landuse.timeseries_0.9x1.25_hist_78pfts_CMIP6_simyr1850-2015_c190214.nc - -[domain] -file = share/domains/domain.lnd.fv0.9x1.25_gx1v7.151020.nc - diff --git a/tools/mksurfdata_map/landuse_timeseries_hist_78pfts_simyr1850-2015.txt b/tools/mksurfdata_map/landuse_timeseries_hist_78pfts_simyr1850-2015.txt deleted file mode 100644 index 3c622f3965..0000000000 --- a/tools/mksurfdata_map/landuse_timeseries_hist_78pfts_simyr1850-2015.txt +++ /dev/null @@ -1,332 +0,0 @@ -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1850.c170412.nc 1850 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1850.c170412.nc 1850 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1851.c170412.nc 1851 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1851.c170412.nc 1851 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1852.c170412.nc 1852 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1852.c170412.nc 1852 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1853.c170412.nc 1853 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1853.c170412.nc 1853 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1854.c170412.nc 1854 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1854.c170412.nc 1854 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1855.c170412.nc 1855 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1855.c170412.nc 1855 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1856.c170412.nc 1856 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1856.c170412.nc 1856 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1857.c170412.nc 1857 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1857.c170412.nc 1857 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1858.c170412.nc 1858 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1858.c170412.nc 1858 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1859.c170412.nc 1859 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1859.c170412.nc 1859 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1860.c170412.nc 1860 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1860.c170412.nc 1860 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1861.c170412.nc 1861 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1861.c170412.nc 1861 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1862.c170412.nc 1862 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1862.c170412.nc 1862 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1863.c170412.nc 1863 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1863.c170412.nc 1863 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1864.c170412.nc 1864 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1864.c170412.nc 1864 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1865.c170412.nc 1865 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1865.c170412.nc 1865 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1866.c170412.nc 1866 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1866.c170412.nc 1866 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1867.c170412.nc 1867 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1867.c170412.nc 1867 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1868.c170412.nc 1868 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1868.c170412.nc 1868 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1869.c170412.nc 1869 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1869.c170412.nc 1869 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1870.c170412.nc 1870 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1870.c170412.nc 1870 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1871.c170412.nc 1871 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1871.c170412.nc 1871 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1872.c170412.nc 1872 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1872.c170412.nc 1872 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1873.c170412.nc 1873 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1873.c170412.nc 1873 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1874.c170412.nc 1874 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1874.c170412.nc 1874 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1875.c170412.nc 1875 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1875.c170412.nc 1875 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1876.c170412.nc 1876 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1876.c170412.nc 1876 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1877.c170412.nc 1877 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1877.c170412.nc 1877 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1878.c170412.nc 1878 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1878.c170412.nc 1878 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1879.c170412.nc 1879 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1879.c170412.nc 1879 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1880.c170412.nc 1880 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1880.c170412.nc 1880 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1881.c170412.nc 1881 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1881.c170412.nc 1881 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1882.c170412.nc 1882 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1882.c170412.nc 1882 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1883.c170412.nc 1883 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1883.c170412.nc 1883 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1884.c170412.nc 1884 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1884.c170412.nc 1884 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1885.c170412.nc 1885 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1885.c170412.nc 1885 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1886.c170412.nc 1886 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1886.c170412.nc 1886 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1887.c170412.nc 1887 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1887.c170412.nc 1887 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1888.c170412.nc 1888 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1888.c170412.nc 1888 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1889.c170412.nc 1889 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1889.c170412.nc 1889 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1890.c170412.nc 1890 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1890.c170412.nc 1890 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1891.c170412.nc 1891 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1891.c170412.nc 1891 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1892.c170412.nc 1892 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1892.c170412.nc 1892 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1893.c170412.nc 1893 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1893.c170412.nc 1893 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1894.c170412.nc 1894 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1894.c170412.nc 1894 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1895.c170412.nc 1895 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1895.c170412.nc 1895 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1896.c170412.nc 1896 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1896.c170412.nc 1896 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1897.c170412.nc 1897 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1897.c170412.nc 1897 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1898.c170412.nc 1898 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1898.c170412.nc 1898 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1899.c170412.nc 1899 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1899.c170412.nc 1899 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1900.c170412.nc 1900 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1900.c170412.nc 1900 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1901.c170412.nc 1901 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1901.c170412.nc 1901 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1902.c170412.nc 1902 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1902.c170412.nc 1902 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1903.c170412.nc 1903 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1903.c170412.nc 1903 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1904.c170412.nc 1904 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1904.c170412.nc 1904 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1905.c170412.nc 1905 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1905.c170412.nc 1905 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1906.c170412.nc 1906 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1906.c170412.nc 1906 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1907.c170412.nc 1907 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1907.c170412.nc 1907 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1908.c170412.nc 1908 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1908.c170412.nc 1908 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1909.c170412.nc 1909 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1909.c170412.nc 1909 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1910.c170412.nc 1910 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1910.c170412.nc 1910 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1911.c170412.nc 1911 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1911.c170412.nc 1911 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1912.c170412.nc 1912 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1912.c170412.nc 1912 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1913.c170412.nc 1913 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1913.c170412.nc 1913 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1914.c170412.nc 1914 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1914.c170412.nc 1914 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1915.c170412.nc 1915 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1915.c170412.nc 1915 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1916.c170412.nc 1916 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1916.c170412.nc 1916 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1917.c170412.nc 1917 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1917.c170412.nc 1917 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1918.c170412.nc 1918 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1918.c170412.nc 1918 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1919.c170412.nc 1919 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1919.c170412.nc 1919 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1920.c170412.nc 1920 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1920.c170412.nc 1920 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1921.c170412.nc 1921 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1921.c170412.nc 1921 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1922.c170412.nc 1922 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1922.c170412.nc 1922 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1923.c170412.nc 1923 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1923.c170412.nc 1923 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1924.c170412.nc 1924 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1924.c170412.nc 1924 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1925.c170412.nc 1925 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1925.c170412.nc 1925 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1926.c170412.nc 1926 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1926.c170412.nc 1926 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1927.c170412.nc 1927 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1927.c170412.nc 1927 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1928.c170412.nc 1928 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1928.c170412.nc 1928 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1929.c170412.nc 1929 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1929.c170412.nc 1929 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1930.c170412.nc 1930 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1930.c170412.nc 1930 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1931.c170412.nc 1931 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1931.c170412.nc 1931 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1932.c170412.nc 1932 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1932.c170412.nc 1932 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1933.c170412.nc 1933 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1933.c170412.nc 1933 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1934.c170412.nc 1934 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1934.c170412.nc 1934 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1935.c170412.nc 1935 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1935.c170412.nc 1935 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1936.c170412.nc 1936 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1936.c170412.nc 1936 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1937.c170412.nc 1937 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1937.c170412.nc 1937 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1938.c170412.nc 1938 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1938.c170412.nc 1938 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1939.c170412.nc 1939 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1939.c170412.nc 1939 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1940.c170412.nc 1940 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1940.c170412.nc 1940 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1941.c170412.nc 1941 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1941.c170412.nc 1941 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1942.c170412.nc 1942 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1942.c170412.nc 1942 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1943.c170412.nc 1943 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1943.c170412.nc 1943 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1944.c170412.nc 1944 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1944.c170412.nc 1944 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1945.c170412.nc 1945 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1945.c170412.nc 1945 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1946.c170412.nc 1946 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1946.c170412.nc 1946 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1947.c170412.nc 1947 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1947.c170412.nc 1947 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1948.c170412.nc 1948 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1948.c170412.nc 1948 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1949.c170412.nc 1949 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1949.c170412.nc 1949 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1950.c170412.nc 1950 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1950.c170412.nc 1950 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1951.c170412.nc 1951 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1951.c170412.nc 1951 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1952.c170412.nc 1952 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1952.c170412.nc 1952 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1953.c170412.nc 1953 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1953.c170412.nc 1953 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1954.c170412.nc 1954 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1954.c170412.nc 1954 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1955.c170412.nc 1955 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1955.c170412.nc 1955 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1956.c170412.nc 1956 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1956.c170412.nc 1956 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1957.c170412.nc 1957 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1957.c170412.nc 1957 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1958.c170412.nc 1958 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1958.c170412.nc 1958 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1959.c170412.nc 1959 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1959.c170412.nc 1959 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1960.c170412.nc 1960 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1960.c170412.nc 1960 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1961.c170412.nc 1961 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1961.c170412.nc 1961 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1962.c170412.nc 1962 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1962.c170412.nc 1962 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1963.c170412.nc 1963 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1963.c170412.nc 1963 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1964.c170412.nc 1964 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1964.c170412.nc 1964 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1965.c170412.nc 1965 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1965.c170412.nc 1965 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1966.c170412.nc 1966 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1966.c170412.nc 1966 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1967.c170412.nc 1967 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1967.c170412.nc 1967 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1968.c170412.nc 1968 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1968.c170412.nc 1968 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1969.c170412.nc 1969 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1969.c170412.nc 1969 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1970.c170412.nc 1970 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1970.c170412.nc 1970 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1971.c170412.nc 1971 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1971.c170412.nc 1971 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1972.c170412.nc 1972 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1972.c170412.nc 1972 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1973.c170412.nc 1973 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1973.c170412.nc 1973 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1974.c170412.nc 1974 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1974.c170412.nc 1974 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1975.c170412.nc 1975 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1975.c170412.nc 1975 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1976.c170412.nc 1976 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1976.c170412.nc 1976 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1977.c170412.nc 1977 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1977.c170412.nc 1977 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1978.c170412.nc 1978 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1978.c170412.nc 1978 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1979.c170412.nc 1979 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1979.c170412.nc 1979 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1980.c170412.nc 1980 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1980.c170412.nc 1980 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1981.c170412.nc 1981 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1981.c170412.nc 1981 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1982.c170412.nc 1982 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1982.c170412.nc 1982 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1983.c170412.nc 1983 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1983.c170412.nc 1983 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1984.c170412.nc 1984 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1984.c170412.nc 1984 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1985.c170412.nc 1985 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1985.c170412.nc 1985 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1986.c170412.nc 1986 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1986.c170412.nc 1986 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1987.c170412.nc 1987 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1987.c170412.nc 1987 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1988.c170412.nc 1988 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1988.c170412.nc 1988 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1989.c170412.nc 1989 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1989.c170412.nc 1989 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1990.c170412.nc 1990 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1990.c170412.nc 1990 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1991.c170412.nc 1991 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1991.c170412.nc 1991 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1992.c170412.nc 1992 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1992.c170412.nc 1992 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1993.c170412.nc 1993 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1993.c170412.nc 1993 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1994.c170412.nc 1994 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1994.c170412.nc 1994 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1995.c170412.nc 1995 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1995.c170412.nc 1995 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1996.c170412.nc 1996 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1996.c170412.nc 1996 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1997.c170412.nc 1997 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1997.c170412.nc 1997 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1998.c170412.nc 1998 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1998.c170412.nc 1998 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1999.c170412.nc 1999 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_1999.c170412.nc 1999 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_2000.c170412.nc 2000 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_2000.c170412.nc 2000 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_2001.c170412.nc 2001 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_2001.c170412.nc 2001 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_2002.c170412.nc 2002 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_2002.c170412.nc 2002 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_2003.c170412.nc 2003 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_2003.c170412.nc 2003 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_2004.c170412.nc 2004 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_2004.c170412.nc 2004 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_2005.c170412.nc 2005 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_2005.c170412.nc 2005 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_2006.c170412.nc 2006 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_2006.c170412.nc 2006 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_2007.c170412.nc 2007 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_2007.c170412.nc 2007 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_2008.c170412.nc 2008 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_2008.c170412.nc 2008 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_2009.c170412.nc 2009 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_2009.c170412.nc 2009 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_2010.c170412.nc 2010 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_2010.c170412.nc 2010 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_2011.c170412.nc 2011 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_2011.c170412.nc 2011 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_2012.c170412.nc 2012 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_2012.c170412.nc 2012 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_2013.c170412.nc 2013 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_2013.c170412.nc 2013 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_2014.c170412.nc 2014 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_2014.c170412.nc 2014 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_2015.c170412.nc 2015 -/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_2015.c170412.nc 2015 diff --git a/tools/mksurfdata_map/mksurfdata.pl b/tools/mksurfdata_map/mksurfdata.pl deleted file mode 100755 index b0363704ae..0000000000 --- a/tools/mksurfdata_map/mksurfdata.pl +++ /dev/null @@ -1,881 +0,0 @@ -#!/usr/bin/env perl -# -# Oct/30/2008 Erik Kluzek -# -# mksurfdata.pl Perl script to make surface datasets for all resolutions. -# -# -use Cwd; -use strict; -use English; -use IO::File; -use Getopt::Long; - - -#Figure out where configure directory is and where can use the XML/Lite module from -my $ProgName; -($ProgName = $PROGRAM_NAME) =~ s!(.*)/!!; # name of program -my $ProgDir = $1; # name of directory where program lives - -my $cwd = getcwd(); # current working directory -my $scrdir; - -if ($ProgDir) { $scrdir = $ProgDir; } -else { $scrdir = $cwd; } - -my $debug = 0; - -#----------------------------------------------------------------------------------------------- -# Add $scrdir to the list of paths that Perl searches for modules -my @dirs = ( "$scrdir/../../cime/utils/perl5lib", - "$scrdir/../../../../cime/utils/perl5lib" - ); -unshift @INC, @dirs; -my $result = eval "require XML::Lite"; -if ( ! defined($result) ) { - die <<"EOF"; -** Cannot find perl module \"XML/Lite.pm\" from directories: @dirs ** -EOF -} -my $result = eval "require Build::NamelistDefinition"; -if ( ! defined($result) ) { - die <<"EOF"; -** Cannot find perl module \"Build/NamelistDefinition.pm\" from directories: @dirs ** -EOF -} -my $nldef_file = "$scrdir/../../bld/namelist_files/namelist_definition_ctsm.xml"; - -my $definition = Build::NamelistDefinition->new( $nldef_file ); - -my $CSMDATA = "/glade/p/cesm/cseg/inputdata"; - -my %opts = ( - hgrid=>"all", - vic=>0, - glc=>0, - ssp_rcp=>"hist", - debug=>0, - exedir=>undef, - allownofile=>undef, - crop=>1, - fast_maps=>0, - hirespft=>undef, - years=>"1850,2000", - glc_nec=>10, - merge_gis=>undef, - inlandwet=>undef, - help=>0, - no_surfdata=>0, - pft_override=>undef, - pft_frc=>undef, - pft_idx=>undef, - soil_override=>undef, - soil_cly=>undef, - soil_snd=>undef, - soil_col=>undef, - soil_fmx=>undef, - outnc_double=>undef, - outnc_dims=>"2", - usrname=>"", - rundir=>"$cwd", - usr_mapdir=>"../mkmapdata", - dynpft=>undef, - csmdata=>$CSMDATA, - urban_skip_abort_on_invalid_data_check=>undef, - ); - -my $numpft = 78; - -#----------------------------------------------------------------------------------------------- -sub usage { - die < [OPTIONS] - -res [or -r] "resolution" is the supported resolution(s) to use for files (by default $opts{'hgrid'} ). - - - For unsupported, user-specified resolutions: - $ProgName -res usrspec -usr_gname -usr_gdate [OPTIONS] - -usr_gname "user_gname" User resolution name to find grid file with - (only used if -res is set to 'usrspec') - -usr_gdate "user_gdate" User map date to find mapping files with - (only used if -res is set to 'usrspec') - NOTE: all mapping files are assumed to be in mkmapdata - - and the user needs to have invoked mkmapdata in - that directory first - -usr_mapdir "mapdirectory" Directory where the user-supplied mapping files are - Default: $opts{'usr_mapdir'} - -OPTIONS - NOTE: The three critical options are (-years, -glc_nec, and -ssp_rcp) they are marked as such. - - -allownofile Allow the script to run even if one of the input files - does NOT exist. - -dinlc [or -l] Enter the directory location for inputdata - (default $opts{'csmdata'}) - -debug [or -d] Do not actually run -- just print out what - would happen if ran. - -dynpft "filename" Dynamic PFT/harvesting file to use if you have a manual list you want to use - (rather than create it on the fly, must be consistent with first year) - (Normally NOT used) - -fast_maps Toggle fast mode which doesn't use the large mapping files - -glc_nec "number" Number of glacier elevation classes to use (by default $opts{'glc_nec'}) - (CRITICAL OPTION) - -merge_gis If you want to use the glacier dataset that merges in - the Greenland Ice Sheet data that CISM uses (typically - used only if consistency with CISM is important) - -hirespft If you want to use the high-resolution pft dataset rather - than the default lower resolution dataset - (low resolution is at half-degree, high resolution at 3minute) - (hires only available for present-day [2000]) - -exedir "directory" Directory where mksurfdata_map program is - (by default assume it is in the current directory) - -inlandwet If you want to allow inland wetlands - -no-crop Create datasets without the extensive list of prognostic crop types - -no_surfdata Do not output a surface dataset - This is useful if you only want a landuse_timeseries file - -years [or -y] "years" Simulation year(s) to run over (by default $opts{'years'}) - (can also be a simulation year range: i.e. 1850-2000 or 1850-2100 for ssp_rcp future scenarios) - (CRITICAL OPTION) - -help [or -h] Display this help. - - -rundir "directory" Directory to run in - (by default current directory $opts{'rundir'}) - - -ssp_rcp "scenario-name" Shared Socioeconomic Pathway and Representative Concentration Pathway Scenario name(s). - "hist" for historical, otherwise in form of SSPn-m.m where n is the SSP number - and m.m is the radiative forcing in W/m^2 at the peak or 2100. - (normally use thiw with -years 1850-2100) - (CRITICAL OPTION) - - -usrname "clm_usrdat_name" CLM user data name to find grid file with. - - -vic Add the fields required for the VIC model - -glc Add the optional 3D glacier fields for verification of the glacier model - - NOTE: years, res, and ssp_rcp can be comma delimited lists. - - -OPTIONS to override the mapping of the input gridded data with hardcoded input - - -pft_frc "list of fractions" Comma delimited list of percentages for veg types - -pft_idx "list of veg index" Comma delimited veg index for each fraction - -soil_cly "% of clay" % of soil that is clay - -soil_col "soil color" Soil color (1 [light] to 20 [dark]) - -soil_fmx "soil fmax" Soil maximum saturated fraction (0-1) - -soil_snd "% of sand" % of soil that is sand - -OPTIONS to work around bugs? - -urban_skip_abort_on_invalid_data_check - do not abort on an invalid data check in urban. - Added 2015-01 to avoid recompiling as noted in - /glade/p/cesm/cseg/inputdata/lnd/clm2/surfdata_map/README_c141219 - -EOF -} - -sub check_soil { -# -# check that the soil options are set correctly -# - foreach my $type ( "soil_cly", "soil_snd" ) { - if ( ! defined($opts{$type} ) ) { - die "ERROR: Soil variables were set, but $type was NOT set\n"; - } - } - #if ( $opts{'soil_col'} < 0 || $opts{'soil_col'} > 20 ) { - # die "ERROR: Soil color is out of range = ".$opts{'soil_col'}."\n"; - #} - my $texsum = $opts{'soil_cly'} + $opts{'soil_snd'}; - my $loam = 100.0 - $texsum; - if ( $texsum < 0.0 || $texsum > 100.0 ) { - die "ERROR: Soil textures are out of range: clay = ".$opts{'soil_cly'}. - " sand = ".$opts{'soil_snd'}." loam = $loam\n"; - } -} - -sub check_soil_col_fmx { -# -# check that the soil color or soil fmax option is set correctly -# - if ( defined($opts{'soil_col'}) ) { - if ( $opts{'soil_col'} < 0 || $opts{'soil_col'} > 20 ) { - die "ERROR: Soil color is out of range = ".$opts{'soil_col'}."\n"; - } - } - if ( defined($opts{'soil_fmx'}) ) { - if ( $opts{'soil_fmx'} < 0.0 || $opts{'soil_fmx'} > 1.0 ) { - die "ERROR: Soil fmax is out of range = ".$opts{'soil_fmx'}."\n"; - } - } -} - -sub check_pft { -# -# check that the pft options are set correctly -# - # Eliminate starting and ending square brackets - $opts{'pft_idx'} =~ s/^\[//; - $opts{'pft_idx'} =~ s/\]$//; - $opts{'pft_frc'} =~ s/^\[//; - $opts{'pft_frc'} =~ s/\]$//; - foreach my $type ( "pft_idx", "pft_frc" ) { - if ( ! defined($opts{$type} ) ) { - die "ERROR: PFT variables were set, but $type was NOT set\n"; - } - } - my @pft_idx = split( /,/, $opts{'pft_idx'} ); - my @pft_frc = split( /,/, $opts{'pft_frc'} ); - if ( $#pft_idx != $#pft_frc ) { - die "ERROR: PFT arrays are different sizes: pft_idx and pft_frc\n"; - } - my $sumfrc = 0.0; - for( my $i = 0; $i <= $#pft_idx; $i++ ) { - # check index in range - if ( $pft_idx[$i] < 0 || $pft_idx[$i] > $numpft ) { - die "ERROR: pft_idx out of range = ".$opts{'pft_idx'}."\n"; - } - # make sure there are no duplicates - for( my $j = 0; $j < $i; $j++ ) { - if ( $pft_idx[$i] == $pft_idx[$j] ) { - die "ERROR: pft_idx has duplicates = ".$opts{'pft_idx'}."\n"; - } - } - # check fraction in range - if ( $pft_frc[$i] <= 0.0 || $pft_frc[$i] > 100.0 ) { - die "ERROR: pft_frc out of range (>0.0 and <=100.0) = ".$opts{'pft_frc'}."\n"; - } - $sumfrc = $sumfrc + $pft_frc[$i]; - } - # check that fraction sums up to 100% - if ( abs( $sumfrc - 100.0) > 1.e-6 ) { - die "ERROR: pft_frc does NOT add up to 100% = ".$opts{'pft_frc'}."\n"; - } - -} - -# Perl trim function to remove whitespace from the start and end of the string -sub trim($) -{ - my $string = shift; - $string =~ s/^\s+//; - $string =~ s/\s+$//; - return $string; -} - -sub write_transient_timeseries_file { - my ($transient, $desc, $sim_yr0, $sim_yrn, $queryfilopts, $resol, $resolhrv, $ssp_rcp, $mkcrop, $sim_yr_surfdat) = @_; - - my $strlen = 195; - my $dynpft_format = "%-${strlen}.${strlen}s %4.4d\n"; - my $landuse_timeseries_text_file = ""; - if ( $transient ) { - if ( ! defined($opts{'dynpft'}) && ! $opts{'pft_override'} ) { - $landuse_timeseries_text_file = "landuse_timeseries_$desc.txt"; - my $fh_landuse_timeseries = IO::File->new; - $fh_landuse_timeseries->open( ">$landuse_timeseries_text_file" ) or die "** can't open file: $landuse_timeseries_text_file\n"; - print "Writing out landuse_timeseries text file: $landuse_timeseries_text_file\n"; - for( my $yr = $sim_yr0; $yr <= $sim_yrn; $yr++ ) { - my $vegtypyr = `$scrdir/../../bld/queryDefaultNamelist.pl $queryfilopts $resol -options sim_year='$yr',ssp_rcp=${ssp_rcp}${mkcrop} -var mksrf_fvegtyp -namelist clmexp`; - chomp( $vegtypyr ); - printf $fh_landuse_timeseries $dynpft_format, $vegtypyr, $yr; - my $hrvtypyr = `$scrdir/../../bld/queryDefaultNamelist.pl $queryfilopts $resolhrv -options sim_year='$yr',ssp_rcp=${ssp_rcp}${mkcrop} -var mksrf_fvegtyp -namelist clmexp`; - chomp( $hrvtypyr ); - printf $fh_landuse_timeseries $dynpft_format, $hrvtypyr, $yr; - if ( $yr % 100 == 0 ) { - print "year: $yr\n"; - } - } - $fh_landuse_timeseries->close; - print "Done writing file\n"; - } elsif ( $opts{'pft_override'} && defined($opts{'dynpft'}) ) { - $landuse_timeseries_text_file = $opts{'dynpft'}; - } else { - $landuse_timeseries_text_file = "landuse_timeseries_override_$desc.txt"; - my $fh_landuse_timeseries = IO::File->new; - $fh_landuse_timeseries->open( ">$landuse_timeseries_text_file" ) or die "** can't open file: $landuse_timeseries_text_file\n"; - my $frstpft = "$opts{'pft_frc'}" . - "$opts{'pft_idx'}" . - "0,0,0,0,00"; - print "Writing out landuse_timeseries text file: $landuse_timeseries_text_file\n"; - if ( (my $len = length($frstpft)) > $strlen ) { - die "ERROR PFT line is too long ($len): $frstpft\n"; - } - # NOTE(wjs, 2014-12-04) Using sim_yr_surfdat here rather than - # sim_yr0. As far as I can tell, it seems somewhat arbitrary which one - # we use, but sim_yr_surfdat seems more like what's intended. - printf $fh_landuse_timeseries $dynpft_format, $frstpft, $sim_yr_surfdat; - $fh_landuse_timeseries->close; - print "Done writing file\n"; - } - } - return $landuse_timeseries_text_file; -} - -sub write_namelist_file { - my ($namelist_fname, $logfile_fname, $fsurdat_fname, $fdyndat_fname, - $glc_nec, $griddata, $gridtype, $map, $datfil, $double, - $all_urb, $no_inlandwet, $vegtyp, $hrvtyp, - $landuse_timeseries_text_file, $setnumpft) = @_; - - - my $gitdescribe = `cd $scrdir; git describe; cd -`; - chomp( $gitdescribe ); - my $fh = IO::File->new; - $fh->open( ">$namelist_fname" ) or die "** can't open file: $namelist_fname\n"; - print $fh <<"EOF"; -&clmexp - nglcec = $glc_nec - mksrf_fgrid = '$griddata' - mksrf_gridtype = '$gridtype' - map_fpft = '$map->{'veg'}' - map_fglacier = '$map->{'glc'}' - map_fglacierregion = '$map->{'glcregion'}' - map_fsoicol = '$map->{'col'}' - map_furban = '$map->{'urb'}' - map_fmax = '$map->{'fmx'}' - map_forganic = '$map->{'org'}' - map_flai = '$map->{'lai'}' - map_fharvest = '$map->{'hrv'}' - map_flakwat = '$map->{'lak'}' - map_fwetlnd = '$map->{'wet'}' - map_fvocef = '$map->{'voc'}' - map_fsoitex = '$map->{'tex'}' - map_furbtopo = '$map->{'utp'}' - map_fgdp = '$map->{'gdp'}' - map_fpeat = '$map->{'peat'}' - map_fsoildepth = '$map->{'soildepth'}' - map_fabm = '$map->{'abm'}' - mksrf_fsoitex = '$datfil->{'tex'}' - mksrf_forganic = '$datfil->{'org'}' - mksrf_flakwat = '$datfil->{'lak'}' - mksrf_fwetlnd = '$datfil->{'wet'}' - mksrf_fmax = '$datfil->{'fmx'}' - mksrf_fglacier = '$datfil->{'glc'}' - mksrf_fglacierregion = '$datfil->{'glcregion'}' - mksrf_fvocef = '$datfil->{'voc'}' - mksrf_furbtopo = '$datfil->{'utp'}' - mksrf_fgdp = '$datfil->{'gdp'}' - mksrf_fpeat = '$datfil->{'peat'}' - mksrf_fsoildepth = '$datfil->{'soildepth'}' - mksrf_fabm = '$datfil->{'abm'}' - outnc_double = $double - all_urban = $all_urb - no_inlandwet = $no_inlandwet - mksrf_furban = '$datfil->{'urb'}' - gitdescribe = '$gitdescribe' -EOF - if ( $opts{'vic'} ) { - print $fh <<"EOF"; - map_fvic = '$map->{'vic'}' - mksrf_fvic = '$datfil->{'vic'}' - outnc_vic = .true. -EOF - } - if ( $opts{'glc'} ) { - print $fh <<"EOF"; - outnc_3dglc = .true. -EOF - } - if ( $opts{'glc'} ) { - print $fh <<"EOF"; - outnc_3dglc = .true. -EOF - } - if ( ! $opts{'fast_maps'} ) { - print $fh <<"EOF"; - map_ftopostats = '$map->{'topostats'}' - mksrf_ftopostats = '$datfil->{'topostats'}' -EOF - } else { - print $fh <<"EOF"; - std_elev = 371.0d00 -EOF - } - if ( defined($opts{'soil_override'}) ) { - print $fh <<"EOF"; - soil_clay = $opts{'soil_cly'} - soil_sand = $opts{'soil_snd'} -EOF - } - if ( defined($opts{'pft_override'}) ) { - print $fh <<"EOF"; - all_veg = .true. - pft_frc = $opts{'pft_frc'} - pft_idx = $opts{'pft_idx'} -EOF - } - - print $fh <<"EOF"; - mksrf_fvegtyp = '$vegtyp' - mksrf_fhrvtyp = '$hrvtyp' - mksrf_fsoicol = '$datfil->{'col'}' - mksrf_flai = '$datfil->{'lai'}' -EOF - - # Note that some of the file names in the following may be empty strings - # (except for logfile_fname) - print $fh <<"EOF"; - fsurdat = '$fsurdat_fname' - fsurlog = '$logfile_fname' - mksrf_fdynuse = '$landuse_timeseries_text_file' - fdyndat = '$fdyndat_fname' -EOF - - if ( $setnumpft ) { - print $fh <<"EOF"; - $setnumpft -EOF - } - - if ( $opts{'urban_skip_abort_on_invalid_data_check'} ) { - print $fh <<"EOF"; - urban_skip_abort_on_invalid_data_check = .true. -EOF - } - # end the namelist - print $fh <<"EOF"; -/ -EOF - - $fh->close; - # - # Print namelist file - $fh->open( "<$namelist_fname" ) or die "** can't open file: $namelist_fname\n"; - while( $_ = <$fh> ) { - print $_; - } - $fh->close; -} - -#----------------------------------------------------------------------------------------------- - - my $cmdline = "@ARGV"; - GetOptions( - "allownofile" => \$opts{'allownofile'}, - "r|res=s" => \$opts{'hgrid'}, - "usr_gname=s" => \$opts{'usr_gname'}, - "usr_gdate=s" => \$opts{'usr_gdate'}, - "usr_mapdir=s" => \$opts{'usr_mapdir'}, - "crop!" => \$opts{'crop'}, - "hirespft" => \$opts{'hirespft'}, - "l|dinlc=s" => \$opts{'csmdata'}, - "d|debug" => \$opts{'debug'}, - "fast_maps" => \$opts{'fast_maps'}, - "dynpft=s" => \$opts{'dynpft'}, - "y|years=s" => \$opts{'years'}, - "exedir=s" => \$opts{'exedir'}, - "h|help" => \$opts{'help'}, - "usrname=s" => \$opts{'usrname'}, - "glc_nec=i" => \$opts{'glc_nec'}, - "merge_gis" => \$opts{'merge_gis'}, - "inlandwet" => \$opts{'inlandwet'}, - "no_surfdata" => \$opts{'no_surfdata'}, - "pft_frc=s" => \$opts{'pft_frc'}, - "pft_idx=s" => \$opts{'pft_idx'}, - "ssp_rcp=s" => \$opts{'ssp_rcp'}, - "vic!" => \$opts{'vic'}, - "glc!" => \$opts{'glc'}, - "rundir=s" => \$opts{'rundir'}, - "soil_col=i" => \$opts{'soil_col'}, - "soil_fmx=f" => \$opts{'soil_fmx'}, - "soil_cly=f" => \$opts{'soil_cly'}, - "soil_snd=f" => \$opts{'soil_snd'}, - "urban_skip_abort_on_invalid_data_check" => \$opts{'urban_skip_abort_on_invalid_data_check'}, - ) or usage(); - - # Check for unparsed arguments - if (@ARGV) { - print "ERROR: unrecognized arguments: @ARGV\n"; - usage(); - } - if ( $opts{'help'} ) { - usage(); - } - - chdir( $opts{'rundir'} ) or die "** can't change to directory: $opts{'rundir'}\n"; - # If csmdata was changed from the default - if ( $CSMDATA ne $opts{'csmdata'} ) { - $CSMDATA = $opts{'csmdata'}; - } - my $glc_nec = $opts{'glc_nec'}; - if ( $glc_nec <= 0 ) { - print "** glc_nec must be at least 1\n"; - usage(); - } - my $no_inlandwet = ".true."; - if (defined($opts{'inlandwet'})) { - $no_inlandwet = ".false."; - } - # - # Set disk location to send files to, and list resolutions to operate over, - # set filenames, and short-date-name - # - my @hresols; - my $mapdate; - if ( $opts{'hgrid'} eq "all" ) { - my @all_hresols = $definition->get_valid_values( "res" ); - @hresols = @all_hresols; - } elsif ( $opts{'hgrid'} eq "usrspec" ) { - @hresols = $opts{'usr_gname'}; - $mapdate = $opts{'usr_gdate'}; - } else { - @hresols = split( ",", $opts{'hgrid'} ); - # Check that resolutions are valid - foreach my $res ( @hresols ) { - if ( ! $definition->is_valid_value( "res", "'$res'" ) ) { - if ( $opts{'usrname'} eq "" || $res ne $opts{'usrname'} ) { - print "** Invalid resolution: $res\n"; - usage(); - } - } - } - } - # - # Set years to run over - # - my @years = split( ",", $opts{'years'} ); - # Check that resolutions are valid - foreach my $sim_year ( @years ) { - if ( ("-" eq substr($sim_year, 4, 1)) || ("-" eq substr($sim_year, 3, 1)) ) { - # range of years for transient run - if ( ! $definition->is_valid_value( "sim_year_range", "'$sim_year'" ) ) { - print "** Invalid simulation simulation year range: $sim_year\n"; - usage(); - } - } else { - # single year. - if ( ! $definition->is_valid_value( "sim_year", "'$sim_year'" ) ) { - print "** Invalid simulation year: $sim_year\n"; - usage(); - } - } - } - # - # Set ssp_rcp to use - # - my @rcpaths = split( ",", $opts{'ssp_rcp'} ); - # Check that ssp_rcp is valid - foreach my $ssp_rcp ( @rcpaths ) { - if ( ! $definition->is_valid_value( "ssp_rcp", "'$ssp_rcp'" ) ) { - print "** Invalid ssp_rcp: $ssp_rcp\n"; - usage(); - } - } - - # CMIP series input data is corresponding to - my $cmip_series = "CMIP6"; - # Check if soil set - if ( defined($opts{'soil_cly'}) || - defined($opts{'soil_snd'}) ) { - &check_soil( ); - $opts{'soil_override'} = 1; - } - # Check if pft set - if ( ! $opts{'crop'} ) { $numpft = 16; } # First set numpft if crop is off - if ( defined($opts{'pft_frc'}) || defined($opts{'pft_idx'}) ) { - &check_pft( ); - $opts{'pft_override'} = 1; - } - # Check if dynpft set and is valid filename - if ( defined($opts{'dynpft'}) ) { - if ( ! -f $opts{'dynpft'} ) { - print "** Dynamic PFT file does NOT exist: $opts{'dynpft'}\n"; - usage(); - } - } - - my $sdate = "c" . `date +%y%m%d`; - chomp( $sdate ); - - my $cfile = "clm.input_data_list"; - if ( -f "$cfile" ) { - `/bin/mv -f $cfile ${cfile}.previous`; - } - my $cfh = IO::File->new; - $cfh->open( ">$cfile" ) or die "** can't open file: $cfile\n"; - system( "\rm -f $cfile" ); - system( "touch $cfile" ); - print $cfh <<"EOF"; -#! /bin/csh -f -set CSMDATA = $CSMDATA -EOF - system( "chmod +x $cfile" ); - my $surfdir = "lnd/clm2/surfdata"; - - # string to add to options for crop off or on - my $mkcrop_off = ",crop='on'"; - my $mkcrop_on = ",crop='on'"; - - # - # Loop over all resolutions and sim-years listed - # - foreach my $res ( @hresols ) { - # - # Query the XML default file database to get the appropriate files - # - my $queryopts, my $queryfilopts; - if ( $opts{'hgrid'} eq "usrspec" ) { - $queryopts = "-csmdata $CSMDATA -silent -justvalue"; - } else { - $queryopts = "-res $res -csmdata $CSMDATA -silent -justvalue"; - } - $queryfilopts = "$queryopts -onlyfiles "; - my $mkcrop = $mkcrop_off; - my $setnumpft = ""; - $mkcrop = $mkcrop_on; - $setnumpft = "numpft = $numpft"; - my $usrnam = ""; - if ( $opts{'usrname'} ne "" && $res eq $opts{'usrname'} ) { - $usrnam = "-usrname ".$opts{'usrname'}; - } - # - # Mapping files - # - my %map; my %hgrd; my %lmsk; my %datfil; my %filnm; - my $hirespft = "off"; - if ( defined($opts{'hirespft'}) ) { - $hirespft = "on"; - } - my $merge_gis = "off"; - if ( defined($opts{'merge_gis'}) ) { - $merge_gis = "on"; - } - my $mopts = "$queryopts -namelist default_settings $usrnam"; - my $mkopts = "-csmdata $CSMDATA -silent -justvalue -namelist clmexp $usrnam"; - my @typlist = ( "lak", "veg", "voc", "tex", "col", "hrv", - "fmx", "lai", "urb", "org", "glc", "glcregion", "utp", "wet", - "gdp", "peat","soildepth","abm"); - if ( $opts{'vic'} ) { - push( @typlist, "vic" ); - } - if ( ! $opts{'fast_maps'} ) { - push( @typlist, "topostats" ); - } - foreach my $typ ( @typlist ) { - my $lmask = `$scrdir/../../bld/queryDefaultNamelist.pl $mopts -options type=$typ,mergeGIS=$merge_gis,hirespft=$hirespft -var lmask`; - $lmask = trim($lmask); - my $hgrid_cmd = "$scrdir/../../bld/queryDefaultNamelist.pl $mopts -options type=$typ,hirespft=$hirespft -var hgrid"; - my $hgrid = `$hgrid_cmd`; - if ($debug) { - print "query to determine hgrid:\n $hgrid_cmd \n\n"; - } - $hgrid = trim($hgrid); - my $filnm = `$scrdir/../../bld/queryDefaultNamelist.pl $mopts -options type=$typ -var mksrf_filename`; - $filnm = trim($filnm); - $filnm{$typ} = $filnm; - $hgrd{$typ} = $hgrid; - $lmsk{$typ} = $lmask; - if ( $opts{'hgrid'} eq "usrspec" ) { - $map{$typ} = $opts{'usr_mapdir'}."/map_${hgrid}_${lmask}_to_${res}_nomask_aave_da_c${mapdate}\.nc"; - } else { - $map{$typ} = `$scrdir/../../bld/queryDefaultNamelist.pl $queryfilopts -namelist clmexp -options frm_hgrid=$hgrid,frm_lmask=$lmask,to_hgrid=$res,to_lmask=nomask -var map`; - } - $map{$typ} = trim($map{$typ}); - if ( $map{$typ} !~ /[^ ]+/ ) { - die "ERROR: could NOT find a mapping file for this resolution: $res and type: $typ at $hgrid and $lmask.\n"; - } - if ( ! defined($opts{'allownofile'}) && ! -f $map{$typ} ) { - die "ERROR: mapping file for this resolution does NOT exist ($map{$typ}).\n"; - } - } - # - # Grid file from the pft map file or grid if not found - # - my $griddata = trim($map{'veg'}); - if ( $griddata eq "" ) { - $griddata = `$scrdir/../../bld/queryDefaultNamelist.pl $queryfilopts $usrnam -var fatmgrid`; - if ( $griddata eq "" ) { - die "ERROR: could NOT find a grid data file for this resolution: $res.\n"; - } - } - my $desc; - my $desc_surfdat; - # - # Check if all urban single point dataset - # - my @all_urb = ( "1x1_vancouverCAN", "1x1_mexicocityMEX", "1x1_urbanc_alpha" ); - my $all_urb = ".false."; - my $urb_pt = 0; - foreach my $urb_res ( @all_urb ) { - if ( $res eq $urb_res ) { - $all_urb = ".true."; - $urb_pt = 1; - } - } - # - # Always run at double precision for output - # - my $double = ".true."; - # - # Loop over each SSP-RCP scenario - # - RCP: foreach my $ssp_rcp ( @rcpaths ) { - # - # Loop over each sim_year - # - SIM_YEAR: foreach my $sim_year ( @years ) { - # - # Skip if urban unless sim_year=2000 - # - if ( $urb_pt && $sim_year ne '2000' ) { - print "For urban -- skip this simulation year = $sim_year\n"; - next SIM_YEAR; - } - # - # If year is 1850-2000 actually run 1850-2015 - # - if ( $sim_year eq "1850-2000" ) { - my $actual = "1850-2015"; - print "For $sim_year actually run $actual\n"; - $sim_year = $actual; - } - my $urbdesc = "urb3den"; - my $resol = "-res $hgrd{'veg'}"; - my $resolhrv = "-res $hgrd{'hrv'}"; - my $sim_yr0 = $sim_year; - my $sim_yrn = $sim_year; - my $transient = 0; - if ( $sim_year =~ /([0-9]+)-([0-9]+)/ ) { - $sim_yr0 = $1; - $sim_yrn = $2; - $transient = 1; - } - # - # Find the file for each of the types - # - foreach my $typ ( @typlist ) { - my $hgrid = $hgrd{$typ}; - my $lmask = $lmsk{$typ}; - my $filnm = $filnm{$typ}; - my $typ_cmd = "$scrdir/../../bld/queryDefaultNamelist.pl $mkopts -options " . - "hgrid=$hgrid,lmask=$lmask,mergeGIS=$merge_gis$mkcrop,sim_year=$sim_yr0 -var $filnm"; - $datfil{$typ} = `$typ_cmd`; - $datfil{$typ} = trim($datfil{$typ}); - if ( $datfil{$typ} !~ /[^ ]+/ ) { - die "ERROR: could NOT find a $filnm data file for this resolution: $hgrid and type: $typ and $lmask.\n$typ_cmd\n\n"; - } - if ( ! defined($opts{'allownofile'}) && ! -f $datfil{$typ} ) { - die "ERROR: data file for this resolution does NOT exist ($datfil{$typ}).\n"; - } - } - # determine simulation year to use for the surface dataset: - my $sim_yr_surfdat = "$sim_yr0"; - - my $cmd = "$scrdir/../../bld/queryDefaultNamelist.pl $queryfilopts $resol -options sim_year='${sim_yr_surfdat}'$mkcrop,ssp_rcp=${ssp_rcp}${mkcrop} -var mksrf_fvegtyp -namelist clmexp"; - my $vegtyp = `$cmd`; - chomp( $vegtyp ); - if ( $vegtyp eq "" ) { - die "** trouble getting vegtyp file with: $cmd\n"; - } - my $cmd = "$scrdir/../../bld/queryDefaultNamelist.pl $queryfilopts $resolhrv -options sim_year='${sim_yr_surfdat}'$mkcrop,ssp_rcp=${ssp_rcp}${mkcrop} -var mksrf_fvegtyp -namelist clmexp"; - my $hrvtyp = `$cmd`; - chomp( $hrvtyp ); - if ( $hrvtyp eq "" ) { - die "** trouble getting hrvtyp file with: $cmd\n"; - } - my $options = ""; - my $crpdes = sprintf("%2.2dpfts", $numpft); - if ( $numpft == 16 ) { - $crpdes .= "_Irrig"; - } - if ( $mkcrop ne "" ) { - $options = "-options $mkcrop"; - } - $desc = sprintf( "%s_%s_%s_simyr%s-%4.4d", $ssp_rcp, $crpdes, $cmip_series, $sim_yr0, $sim_yrn ); - $desc_surfdat = sprintf( "%s_%s_%s_simyr%s", $ssp_rcp, $crpdes, $cmip_series, $sim_yr_surfdat ); - - my $fsurdat_fname_base = ""; - my $fsurdat_fname = ""; - if ( ! $opts{'no_surfdata'} ) { - $fsurdat_fname_base = "surfdata_${res}_${desc_surfdat}_${sdate}"; - $fsurdat_fname = "${fsurdat_fname_base}.nc"; - } - - my $fdyndat_fname_base = ""; - my $fdyndat_fname = ""; - if ($transient) { - $fdyndat_fname_base = "landuse.timeseries_${res}_${desc}_${sdate}"; - $fdyndat_fname = "${fdyndat_fname_base}.nc"; - } - - if (!$fsurdat_fname && !$fdyndat_fname) { - die("ERROR: Tried to run mksurfdata_map without creating either a surface dataset or a landuse.timeseries file") - } - - my $logfile_fname; - my $namelist_fname; - if ($fsurdat_fname_base) { - $logfile_fname = "${fsurdat_fname_base}.log"; - $namelist_fname = "${fsurdat_fname_base}.namelist"; - } - else { - $logfile_fname = "${fdyndat_fname_base}.log"; - $namelist_fname = "${fdyndat_fname_base}.namelist"; - } - - my ($landuse_timeseries_text_file) = write_transient_timeseries_file( - $transient, $desc, $sim_yr0, $sim_yrn, - $queryfilopts, $resol, $resolhrv, $ssp_rcp, $mkcrop, - $sim_yr_surfdat); - - print "CSMDATA is $CSMDATA \n"; - print "resolution: $res ssp_rcp=$ssp_rcp sim_year = $sim_year\n"; - print "namelist: $namelist_fname\n"; - - my $gridtype; - $gridtype = "global"; - if (index($res, '1x1_') != -1) { - $gridtype = "regional"; - } - if (index($res, '5x5_amazon') != -1) { - $gridtype = "regional"; - } - - write_namelist_file( - $namelist_fname, $logfile_fname, $fsurdat_fname, $fdyndat_fname, - $glc_nec, $griddata, $gridtype, \%map, \%datfil, $double, - $all_urb, $no_inlandwet, $vegtyp, $hrvtyp, - $landuse_timeseries_text_file, $setnumpft); - - # - # Delete previous versions of files that will be created - # - system( "/bin/rm -f $fsurdat_fname $logfile_fname" ); - # - # Run mksurfdata_map with the namelist file - # - my $exedir = $scrdir; - if ( defined($opts{'exedir'}) ) { - $exedir = $opts{'exedir'}; - } - print "$exedir/mksurfdata_map < $namelist_fname\n"; - if ( ! $opts{'debug'} ) { - system( "$exedir/mksurfdata_map < $namelist_fname" ); - if ( $? ) { die "ERROR in mksurfdata_map: $?\n"; } - } - print "\n===========================================\n\n"; - - # - # If urban point, overwrite urban variables from previous surface dataset to this one - # - if ( $urb_pt && ! $opts{'no_surfdata'} ) { - my $prvsurfdata = `$scrdir/../../bld/queryDefaultNamelist.pl $queryopts -var fsurdat`; - if ( $? != 0 ) { - die "ERROR:: previous surface dataset file NOT found\n"; - } - chomp( $prvsurfdata ); - my $varlist = "CANYON_HWR,EM_IMPROAD,EM_PERROAD,EM_ROOF,EM_WALL,HT_ROOF,THICK_ROOF,THICK_WALL,T_BUILDING_MIN,WIND_HGT_CANYON,WTLUNIT_ROOF,WTROAD_PERV,ALB_IMPROAD_DIR,ALB_IMPROAD_DIF,ALB_PERROAD_DIR,ALB_PERROAD_DIF,ALB_ROOF_DIR,ALB_ROOF_DIF,ALB_WALL_DIR,ALB_WALL_DIF,TK_ROOF,TK_WALL,TK_IMPROAD,CV_ROOF,CV_WALL,CV_IMPROAD,NLEV_IMPROAD,PCT_URBAN,URBAN_REGION_ID"; - print "Overwrite urban parameters with previous surface dataset values\n"; - $cmd = "ncks -A -v $varlist $prvsurfdata $fsurdat_fname"; - print "$cmd\n"; - if ( ! $opts{'debug'} ) { system( $cmd ); } - } - - } # End of sim_year loop - } # End of ssp_rcp loop - } - close( $cfh ); - print "Successfully created fsurdat files\n"; diff --git a/tools/mksurfdata_map/mksurfdata_map.namelist b/tools/mksurfdata_map/mksurfdata_map.namelist deleted file mode 100644 index 4e00ae1805..0000000000 --- a/tools/mksurfdata_map/mksurfdata_map.namelist +++ /dev/null @@ -1,52 +0,0 @@ -&clmexp - nglcec = 10 - mksrf_fgrid = '/glade/p/cesm/cseg/inputdata/lnd/clm2/mappingdata/maps/10x15/map_0.25x0.25_nomask_to_10x15_nomask_aave_da_c200309.nc' - map_fpft = '/glade/p/cesm/cseg/inputdata/lnd/clm2/mappingdata/maps/10x15/map_0.25x0.25_nomask_to_10x15_nomask_aave_da_c200309.nc' - map_fglacier = '/glade/p/cesm/cseg/inputdata/lnd/clm2/mappingdata/maps/10x15/map_3x3min_nomask_to_10x15_nomask_aave_da_c200309.nc' - map_fglacierregion = '/glade/p/cesm/cseg/inputdata/lnd/clm2/mappingdata/maps/10x15/map_10x10min_nomask_to_10x15_nomask_aave_da_c200206.nc' - map_fsoicol = '/glade/p/cesm/cseg/inputdata/lnd/clm2/mappingdata/maps/10x15/map_0.25x0.25_nomask_to_10x15_nomask_aave_da_c200309.nc' - map_furban = '/glade/p/cesm/cseg/inputdata/lnd/clm2/mappingdata/maps/10x15/map_3x3min_nomask_to_10x15_nomask_aave_da_c200309.nc' - map_fmax = '/glade/p/cesm/cseg/inputdata/lnd/clm2/mappingdata/maps/10x15/map_0.125x0.125_nomask_to_10x15_nomask_aave_da_c200206.nc' - map_forganic = '/glade/p/cesm/cseg/inputdata/lnd/clm2/mappingdata/maps/10x15/map_5x5min_nomask_to_10x15_nomask_aave_da_c200309.nc' - map_flai = '/glade/p/cesm/cseg/inputdata/lnd/clm2/mappingdata/maps/10x15/map_0.25x0.25_nomask_to_10x15_nomask_aave_da_c200309.nc' - map_fharvest = '/glade/p/cesm/cseg/inputdata/lnd/clm2/mappingdata/maps/10x15/map_0.25x0.25_nomask_to_10x15_nomask_aave_da_c200309.nc' - map_flakwat = '/glade/p/cesm/cseg/inputdata/lnd/clm2/mappingdata/maps/10x15/map_3x3min_nomask_to_10x15_nomask_aave_da_c200309.nc' - map_fwetlnd = '/glade/p/cesm/cseg/inputdata/lnd/clm2/mappingdata/maps/10x15/map_0.5x0.5_nomask_to_10x15_nomask_aave_da_c200206.nc' - map_fvocef = '/glade/p/cesm/cseg/inputdata/lnd/clm2/mappingdata/maps/10x15/map_0.5x0.5_nomask_to_10x15_nomask_aave_da_c200206.nc' - map_fsoitex = '/glade/p/cesm/cseg/inputdata/lnd/clm2/mappingdata/maps/10x15/map_5x5min_nomask_to_10x15_nomask_aave_da_c200309.nc' - map_furbtopo = '/glade/p/cesm/cseg/inputdata/lnd/clm2/mappingdata/maps/10x15/map_10x10min_nomask_to_10x15_nomask_aave_da_c200206.nc' - map_fgdp = '/glade/p/cesm/cseg/inputdata/lnd/clm2/mappingdata/maps/10x15/map_0.5x0.5_nomask_to_10x15_nomask_aave_da_c200206.nc' - map_fpeat = '/glade/p/cesm/cseg/inputdata/lnd/clm2/mappingdata/maps/10x15/map_0.5x0.5_nomask_to_10x15_nomask_aave_da_c200206.nc' - map_fsoildepth = '/glade/p/cesm/cseg/inputdata/lnd/clm2/mappingdata/maps/10x15/map_5x5min_nomask_to_10x15_nomask_aave_da_c200309.nc' - map_fabm = '/glade/p/cesm/cseg/inputdata/lnd/clm2/mappingdata/maps/10x15/map_0.5x0.5_nomask_to_10x15_nomask_aave_da_c200206.nc' - map_ftopostats = '/glade/p/cesm/cseg/inputdata/lnd/clm2/mappingdata/maps/10x15/map_1km-merge-10min_HYDRO1K-merge-nomask_to_10x15_nomask_aave_da_c130411.nc' - map_fvic = '/glade/p/cesm/cseg/inputdata/lnd/clm2/mappingdata/maps/10x15/map_0.9x1.25_nomask_to_10x15_nomask_aave_da_c200206.nc' - mksrf_fsoitex = '/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/mksrf_soitex.10level.c010119.nc' - mksrf_forganic = '/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/mksrf_organic_10level_5x5min_ISRIC-WISE-NCSCD_nlev7_c120830.nc' - mksrf_flakwat = '/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/mksrf_LakePnDepth_3x3min_simyr2004_csplk_c151015.nc' - mksrf_fwetlnd = '/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/mksrf_lanwat.050425.nc' - mksrf_fmax = '/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/mksrf_fmax_0.125x0.125_c200220.nc' - mksrf_fglacier = '/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/mksrf_glacier_3x3min_simyr2000.c120926.nc' - mksrf_fglacierregion = '/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/mksrf_GlacierRegion_10x10min_nomask_c191120.nc' - mksrf_fvocef = '/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/mksrf_vocef_0.5x0.5_simyr2000.c110531.nc' - mksrf_furbtopo = '/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/mksrf_topo.10min.c191120.nc' - mksrf_fgdp = '/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/mksrf_gdp_0.5x0.5_AVHRR_simyr2000.c130228.nc' - mksrf_fpeat = '/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/mksrf_peatf_0.5x0.5_AVHRR_simyr2000.c130228.nc' - mksrf_fsoildepth = '/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/mksf_soilthk_5x5min_ORNL-Soil_simyr1900-2015_c170630.nc' - mksrf_fabm = '/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/mksrf_abm_0.5x0.5_AVHRR_simyr2000.c130201.nc' - mksrf_ftopostats = '/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/mksrf_topostats_1km-merge-10min_HYDRO1K-merge-nomask_simyr2000.c130402.nc' - mksrf_fvic = '/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/mksrf_vic_0.9x1.25_GRDC_simyr2000.c130307.nc' - outnc_double = .true. - all_urban = .false. - no_inlandwet = .true. - mksrf_furban = '/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/mksrf_urban_0.05x0.05_simyr2000.c170724.nc' - mksrf_fvegtyp = '/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_2000.c170412.nc' - mksrf_fhrvtyp = '/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_landuse_histclm50_LUH2_2000.c170412.nc' - mksrf_fsoicol = '/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_soilcolor_simyr2005.c170413.nc' - mksrf_flai = '/glade/p/cesm/cseg/inputdata/lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_lai_78pfts_simyr2005.c170413.nc' - fsurdat = 'surfdata_10x15_78pfts_simyr2000_c170531.nc' - fsurlog = 'surfdata_10x15_78pfts_simyr2000_c170531.log' - mksrf_fdynuse = '' - fdyndat = '' - numpft = 78 -/ diff --git a/tools/mksurfdata_map/single_point_dynpft_files/README b/tools/mksurfdata_map/single_point_dynpft_files/README deleted file mode 100644 index 04334d4cb2..0000000000 --- a/tools/mksurfdata_map/single_point_dynpft_files/README +++ /dev/null @@ -1,4 +0,0 @@ -$CTSMROOT/tools/mksurfdata_map/single_point_dynpft_files - -This directory contains files that can be used with the -dynpft option to -mksurfdata.pl when creating the respective single-point transient datasets. diff --git a/tools/mksurfdata_map/single_point_dynpft_files/README.landuse_timeseries_smallvilleIA_hist_simyr1850-1855 b/tools/mksurfdata_map/single_point_dynpft_files/README.landuse_timeseries_smallvilleIA_hist_simyr1850-1855 deleted file mode 100644 index 9cc79f0ecd..0000000000 --- a/tools/mksurfdata_map/single_point_dynpft_files/README.landuse_timeseries_smallvilleIA_hist_simyr1850-1855 +++ /dev/null @@ -1,23 +0,0 @@ -The file landuse_timeseries_smallvilleIA_hist_simyr1850-1855.txt is meant for -use with the 1x1_smallvilleIA test case. It tests a number of aspects of -transient crops: - -- It starts with two years of 100% natural veg (1850 & 1851) - -- It then transitions to 100% crop (1852) - -- It then shifts PCT_CFT while keeping PCT_CROP at 100% (1853) - -- It then increases natural veg to > 0, while also shifting PCT_CFT (1854) - -- It then adjusts both PCT_CROP and PCT_CFT (1855) - -To create a surface dataset and transient dataset that use this file: - -mksurfdata.pl -crop -y 1850-2000 -r 1x1_smallvilleIA -pft_idx 13 -pft_frc 100 -dynpft single_point_dynpft_files/landuse_timeseries_smallvilleIA_hist_simyr1850-1855.txt -mv landuse.timeseries_1x1_smallvilleIA_hist_simyr1850-2005_cYYMMDD.nc landuse.timeseries_1x1_smallvilleIA_hist_simyr1850-1855_cYYMMDD.nc - - -This should be run with a transient crop case that starts in 1850 and runs for -at least 6 years. - diff --git a/tools/mksurfdata_map/single_point_dynpft_files/landuse_timeseries_smallvilleIA_hist_simyr1850-1855.txt b/tools/mksurfdata_map/single_point_dynpft_files/landuse_timeseries_smallvilleIA_hist_simyr1850-1855.txt deleted file mode 100644 index f6943e957f..0000000000 --- a/tools/mksurfdata_map/single_point_dynpft_files/landuse_timeseries_smallvilleIA_hist_simyr1850-1855.txt +++ /dev/null @@ -1,6 +0,0 @@ -100130,0,0,0,00 1850 -100130,0,0,0,00 1851 -1,1,1,1,1,1,1,1,1,9115,16,17,18,19,20,21,22,23,240,0,0,0,00 1852 -91,1,1,1,1,1,1,1,1,115,16,17,18,19,20,21,22,23,240,0,0,0,00 1853 -50,1,2,2,3,3,4,4,5,5,2113,15,16,17,18,19,20,21,22,23,240,0,0,0,00 1854 -75,1,1,1,1,1,1,1,1,1,1613,15,16,17,18,19,20,21,22,23,240,0,0,0,00 1855 diff --git a/tools/mksurfdata_map/src/CMakeLists.txt b/tools/mksurfdata_map/src/CMakeLists.txt deleted file mode 100644 index 3179c3cdc9..0000000000 --- a/tools/mksurfdata_map/src/CMakeLists.txt +++ /dev/null @@ -1,43 +0,0 @@ -# This CMakeLists.txt file is currently used just for building unit tests. - -cmake_minimum_required(VERSION 2.8) -list(APPEND CMAKE_MODULE_PATH ${CIME_CMAKE_MODULE_DIRECTORY}) -include(CIME_initial_setup) - -project(mksurfdat_tests Fortran) - -include(CIME_utils) - -# Build library containing stuff needed for the unit tests -list(APPEND mksurfdat_sources - shr_kind_mod.F90 - shr_log_mod.F90 - nanMod.F90 - shr_string_mod.F90 - fileutils.F90 - shr_timer_mod.F90 - shr_file_mod.F90 - mkgridmapMod.F90 - mkindexmapMod.F90 - mkpftConstantsMod.F90 - mkpctPftTypeMod.F90 - mkpftMod.F90 - mkdomainMod.F90 - mkgridmapMod.F90 - mkutilsMod.F90 - mkpftUtilsMod.F90 - mksoilUtilsMod.F90 - mkvarctl.F90 - mkvarpar.F90 - shr_const_mod.F90 - shr_sys_mod.F90 - unit_test_stubs/abort.F90 - unit_test_stubs/mkncdio.F90) -add_library(mksurfdat ${mksurfdat_sources}) - -# Tell cmake to look for libraries & mod files here, because this is where we built libraries -include_directories(${CMAKE_CURRENT_BINARY_DIR}) -link_directories(${CMAKE_CURRENT_BINARY_DIR}) - -# Add the test directory -add_subdirectory(test) diff --git a/tools/mksurfdata_map/src/Filepath b/tools/mksurfdata_map/src/Filepath deleted file mode 100644 index 9c558e357c..0000000000 --- a/tools/mksurfdata_map/src/Filepath +++ /dev/null @@ -1 +0,0 @@ -. diff --git a/tools/mksurfdata_map/src/Makefile b/tools/mksurfdata_map/src/Makefile deleted file mode 100644 index 248a913565..0000000000 --- a/tools/mksurfdata_map/src/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# Makefile for mksurfdata_map - -EXENAME = ../mksurfdata_map - -# Set optimization on by default -ifeq ($(OPT),$(null)) - OPT := TRUE -endif - -include Makefile.common \ No newline at end of file diff --git a/tools/mksurfdata_map/src/Makefile.common b/tools/mksurfdata_map/src/Makefile.common deleted file mode 100644 index ab79f94144..0000000000 --- a/tools/mksurfdata_map/src/Makefile.common +++ /dev/null @@ -1,360 +0,0 @@ -#----------------------------------------------------------------------- -# This Makefile is for building clm tools on AIX, Linux (with pgf90 or -# lf95 compiler), Darwin or IRIX platforms. -# -# These macros can be changed by setting environment variables: -# -# LIB_NETCDF --- Library directory location of netcdf. (defaults to /usr/local/lib) -# INC_NETCDF --- Include directory location of netcdf. (defaults to /usr/local/include) -# MOD_NETCDF --- Module directory location of netcdf. (defaults to $LIB_NETCDF) -# USER_FC ------ Allow user to override the default Fortran compiler specified in Makefile. -# USER_FCTYP --- Allow user to override the default type of Fortran compiler (linux and USER_FC=ftn only). -# USER_CC ------ Allow user to override the default C compiler specified in Makefile (linux only). -# USER_LINKER -- Allow user to override the default linker specified in Makefile. -# USER_CPPDEFS - Additional CPP defines. -# USER_CFLAGS -- Additional C compiler flags that the user wishes to set. -# USER_FFLAGS -- Additional Fortran compiler flags that the user wishes to set. -# USER_LDLAGS -- Additional load flags that the user wishes to set. -# SMP ---------- Shared memory Multi-processing (TRUE or FALSE) [default is FALSE] -# OPT ---------- Use optimized options. -# -#------------------------------------------------------------------------ - -# Set up special characters -null := - -# Newer makes set the CURDIR variable. -CURDIR := $(shell pwd) - -RM = rm - -# Check for the netcdf library and include directories -ifeq ($(LIB_NETCDF),$(null)) - LIB_NETCDF := /usr/local/lib -endif - -ifeq ($(INC_NETCDF),$(null)) - INC_NETCDF := /usr/local/include -endif - -ifeq ($(MOD_NETCDF),$(null)) - MOD_NETCDF := $(LIB_NETCDF) -endif - -# Set user specified Fortran compiler -ifneq ($(USER_FC),$(null)) - FC := $(USER_FC) -endif - -# Set user specified C compiler -ifneq ($(USER_CC),$(null)) - CC := $(USER_CC) -endif - -# Set if Shared memory multi-processing will be used -ifeq ($(SMP),$(null)) - SMP := FALSE -endif - -CPPDEF := $(USER_CPPDEFS) - -# Set optimization on by default -ifeq ($(OPT),$(null)) - OPT := TRUE -endif - -ifeq ($(OPT),TRUE) - CPPDEF := -DOPT -endif - -# Determine platform -UNAMES := $(shell uname -s) - -# Load dependency search path. -dirs := . $(shell cat Filepath) - -# Set cpp search path, include netcdf -cpp_dirs := $(dirs) $(INC_NETCDF) $(MOD_NETCDF) -cpp_path := $(foreach dir,$(cpp_dirs),-I$(dir)) # format for command line - -# Expand any tildes in directory names. Change spaces to colons. -# (the vpath itself is set elsewhere, based on this variable) -vpath_dirs := $(foreach dir,$(cpp_dirs),$(wildcard $(dir))) -vpath_dirs := $(subst $(space),:,$(vpath_dirs)) - -#Primary Target: build the tool -all: $(EXENAME) - -# Get list of files and build dependency file for all .o files -# using perl scripts mkSrcfiles and mkDepends - -SOURCES := $(shell cat Srcfiles) - -OBJS := $(addsuffix .o, $(basename $(SOURCES))) - -# Set path to Mkdepends script; assumes that any Makefile including -# this file is in a sibling of the src directory, in which Mkdepends -# resides -Mkdepends := ../src/Mkdepends - -$(CURDIR)/Depends: $(CURDIR)/Srcfiles $(CURDIR)/Filepath - $(Mkdepends) Filepath Srcfiles > $@ - - -# Architecture-specific flags and rules -#------------------------------------------------------------------------ -# AIX -#------------------------------------------------------------------------ - -ifeq ($(UNAMES),AIX) -CPPDEF += -DAIX -cpre = $(null)-WF,-D$(null) -FPPFLAGS := $(patsubst -D%,$(cpre)%,$(CPPDEF)) -FFLAGS = -c -I$(INC_NETCDF) -q64 -qsuffix=f=f90 -qsuffix=f=f90:cpp=F90 \ - $(FPPFLAGS) -g -qfullpath -qarch=auto -qtune=auto -qsigtrap=xl__trcedump -qsclk=micro - -LDFLAGS = -L$(LIB_NETCDF) -q64 -lnetcdff -lnetcdf -ifneq ($(OPT),TRUE) - FFLAGS += -qinitauto=7FF7FFFF -qflttrap=ov:zero:inv:en -qspillsize=4000 -C -else - FFLAGS += -O2 -qmaxmem=-1 -Q - LDFLAGS += -Q -endif -CFLAGS := -q64 -g $(CPPDEF) -O2 -FFLAGS += $(cpp_path) -CFLAGS += $(cpp_path) - -ifeq ($(SMP),TRUE) - FC = xlf90_r - FFLAGS += -qsmp=omp - LDFLAGS += -qsmp=omp -else - FC = xlf90 -endif - -endif - -#------------------------------------------------------------------------ -# Darwin -#------------------------------------------------------------------------ - -ifeq ($(UNAMES),Darwin) - -# Set the default Fortran compiler -ifeq ($(USER_FC),$(null)) - FC := g95 -endif -ifeq ($(USER_CC),$(null)) - CC := gcc -endif - -CFLAGS := -g -O2 -CPPDEF += -DSYSDARWIN -DDarwin -DLINUX -LDFLAGS := - -ifeq ($(FC),g95) - - CPPDEF += -DG95 - FFLAGS := -c -fno-second-underscore $(CPPDEF) $(cpp_path) -I$(MOD_NETCDF) - ifeq ($(OPT),TRUE) - FFLAGS += -O2 - else - FFLAGS += -g -fbounds-check - endif - -endif - -ifeq ($(FC),gfortran) - - CPPDEF += -DG95 - FFLAGS := -c -fno-second-underscore $(CPPDEF) $(cpp_path) -I$(MOD_NETCDF) \ - -fno-range-check - ifeq ($(OPT),TRUE) - FFLAGS += -O2 - else - FFLAGS += -g -fbounds-check - endif - -endif - -ifeq ($(FC),ifort) - - CPPDEF += -DFORTRANUNDERSCORE - FFLAGS += -c -ftz -g -fp-model precise $(CPPDEF) $(cpp_path) \ - -convert big_endian -assume byterecl -traceback -FR - LDFLAGS += -m64 - - ifneq ($(OPT),TRUE) - FFLAGS += -CB -O0 - else - FFLAGS += -O2 - endif - ifeq ($(SMP),TRUE) - FFLAGS += -qopenmp - LDFLAGS += -qopenmp - endif -endif - -ifeq ($(FC),pgf90) - - CPPDEF += -DFORTRANUNDERSCORE - FFLAGS += -c $(CPPDEF) $(cpp_path) - ifneq ($(OPT),TRUE) - FFLAGS += -g -Ktrap=fp -Mbounds -Kieee - else - FFLAGS += -fast -Kieee - endif - - ifeq ($(SMP),TRUE) - FFLAGS += -mp - LDFLAGS += -mp - endif - -endif - -ifeq ($(CC),icc) - CFLAGS += -m64 -g - ifeq ($(SMP),TRUE) - CFLAGS += -qopenmp - endif -endif -ifeq ($(CC),pgcc) - CFLAGS += -g -fast -endif - -CFLAGS += $(CPPDEF) $(cpp_path) -LDFLAGS += -L$(LIB_NETCDF) -lnetcdf -lnetcdff - -endif - -#------------------------------------------------------------------------ -# Linux -#------------------------------------------------------------------------ - -ifeq ($(UNAMES),Linux) - ifeq ($(USER_FC),$(null)) - FC := ifort - FCTYP := ifort - else - ifeq ($(USER_FC),ftn) - ifneq ($(USER_FCTYP),$(null)) - FCTYP := $(USER_FCTYP) - else - FCTYP := pgf90 - endif - else - FCTYP := $(USER_FC) - endif - endif - CPPDEF += -DLINUX -DFORTRANUNDERSCORE - CFLAGS := $(CPPDEF) - LDFLAGS := $(shell $(LIB_NETCDF)/../bin/nf-config --flibs) - FFLAGS = - - ifeq ($(FCTYP),pgf90) - CC := pgcc - ifneq ($(OPT),TRUE) - FFLAGS += -g -Ktrap=fp -Mbounds -Kieee - else - FFLAGS += -fast -Kieee - CFLAGS += -fast - endif - - ifeq ($(SMP),TRUE) - FFLAGS += -mp - LDFLAGS += -mp - endif - - endif - - ifeq ($(FCTYP),lf95) - ifneq ($(OPT),TRUE) - FFLAGS += -g --chk a,e,s,u -O0 - else - FFLAGS += -O - endif - # Threading only works by putting thread memory on the heap rather than the stack - # (--threadheap). - # As of lf95 version 6.2 the thread stacksize limits are (still) too small to run - # even small - # resolution problems (FV at 10x15 res fails). - ifeq ($(SMP),TRUE) - FFLAGS += --openmp --threadheap 4096 - LDFLAGS += --openmp --threadheap 4096 - endif - endif - ifeq ($(FCTYP),pathf90) - FFLAGS += -extend_source -ftpp -fno-second-underscore - ifneq ($(OPT),TRUE) - FFLAGS += -g -O0 - else - FFLAGS += -O - endif - ifeq ($(SMP),TRUE) - FFLAGS += -mp - LDFLAGS += -mp - endif - endif - ifeq ($(FCTYP),ifort) - - FFLAGS += -ftz -g -fp-model precise -convert big_endian -assume byterecl -traceback -FR - CFLAGS += -m64 -g - LDFLAGS += -m64 - - ifneq ($(OPT),TRUE) - FFLAGS += -CB -O0 - else - FFLAGS += -O2 - endif - ifeq ($(SMP),TRUE) - FFLAGS += -qopenmp - CFLAGS += -qopenmp - LDFLAGS += -qopenmp - endif - endif - FFLAGS += -c -I$(INC_NETCDF) $(CPPDEF) $(cpp_path) - CFLAGS += $(cpp_path) -endif - -#------------------------------------------------------------------------ -# Default rules and macros -#------------------------------------------------------------------------ - -.SUFFIXES: -.SUFFIXES: .F90 .c .o - -# Set the vpath for all file types EXCEPT .o -# We do this for individual file types rather than generally using -# VPATH, because for .o files, we don't want to use files from a -# different build (e.g., in building the unit tester, we don't want to -# use .o files from the main build) -vpath %.F90 $(vpath_dirs) -vpath %.c $(vpath_dirs) -vpath %.h $(vpath_dirs) - -# Append user defined compiler and load flags to Makefile defaults -CFLAGS += $(USER_CFLAGS) -FFLAGS += $(USER_FFLAGS) -LDFLAGS += $(USER_LDFLAGS) - -# Set user specified linker -ifneq ($(USER_LINKER),$(null)) - LINKER := $(USER_LINKER) -else - LINKER := $(FC) -endif - -.F90.o: - $(FC) $(FFLAGS) $< - -.c.o: - $(CC) -c $(CFLAGS) $< - - -$(EXENAME): $(OBJS) - $(LINKER) -o $@ $(OBJS) $(LDFLAGS) - -clean: - $(RM) -f $(OBJS) *.mod Depends - -include $(CURDIR)/Depends diff --git a/tools/mksurfdata_map/src/Mkdepends b/tools/mksurfdata_map/src/Mkdepends deleted file mode 100755 index ddb1682da4..0000000000 --- a/tools/mksurfdata_map/src/Mkdepends +++ /dev/null @@ -1,328 +0,0 @@ -#!/usr/bin/env perl - -# Generate dependencies in a form suitable for inclusion into a Makefile. -# The source filenames are provided in a file, one per line. Directories -# to be searched for the source files and for their dependencies are provided -# in another file, one per line. Output is written to STDOUT. -# -# For CPP type dependencies (lines beginning with #include) the dependency -# search is recursive. Only dependencies that are found in the specified -# directories are included. So, for example, the standard include file -# stdio.h would not be included as a dependency unless /usr/include were -# one of the specified directories to be searched. -# -# For Fortran module USE dependencies (lines beginning with a case -# insensitive "USE", possibly preceded by whitespace) the Fortran compiler -# must be able to access the .mod file associated with the .o file that -# contains the module. In order to correctly generate these dependencies -# two restrictions must be observed. -# 1) All modules must be contained in files that have the same base name as -# the module, in a case insensitive sense. This restriction implies that -# there can only be one module per file. -# 2) All modules that are to be contained in the dependency list must be -# contained in one of the source files in the list provided on the command -# line. -# The reason for the second restriction is that since the makefile doesn't -# contain rules to build .mod files the dependency takes the form of the .o -# file that contains the module. If a module is being used for which the -# source code is not available (e.g., a module from a library), then adding -# a .o dependency for that module is a mistake because make will attempt to -# build that .o file, and will fail if the source code is not available. -# -# Author: B. Eaton -# Climate Modelling Section, NCAR -# Feb 2001 - -use Getopt::Std; -use File::Basename; -use File::Glob ':bsd_glob'; - -# Check for usage request. -@ARGV >= 2 or usage(); - -# Process command line. -my %opt = (); -getopts( "t:w", \%opt ) or usage(); -my $filepath_arg = shift() or usage(); -my $srcfile_arg = shift() or usage(); -@ARGV == 0 or usage(); # Check that all args were processed. - -my $obj_dir; -if ( defined $opt{'t'} ) { $obj_dir = $opt{'t'}; } - -open(FILEPATH, $filepath_arg) or die "Can't open $filepath_arg: $!\n"; -open(SRCFILES, $srcfile_arg) or die "Can't open $srcfile_arg: $!\n"; - -# Make list of paths to use when looking for files. -# Prepend "." so search starts in current directory. This default is for -# consistency with the way GNU Make searches for dependencies. -my @file_paths = ; -close(FILEPATH); -chomp @file_paths; -unshift(@file_paths,'.'); -foreach $dir (@file_paths) { # (could check that directories exist here) - $dir =~ s!/?\s*$!!; # remove / and any whitespace at end of directory name - ($dir) = bsd_glob $dir; # Expand tildes in path names. -} - -# Make list of files containing source code. -my @src = ; -close(SRCFILES); -chomp @src; - -# For each file that may contain a Fortran module (*.[fF]90 *.[fF]) convert the -# file's basename to uppercase and use it as a hash key whose value is the file's -# basename. This allows fast identification of the files that contain modules. -# The only restriction is that the file's basename and the module name must match -# in a case insensitive way. -my %module_files = (); -my ($f, $name, $path, $suffix, $mod); -my @suffixes = ('\.[fF]90', '\.[fF]' ); -foreach $f (@src) { - ($name, $path, $suffix) = fileparse($f, @suffixes); - ($mod = $name) =~ tr/a-z/A-Z/; - $module_files{$mod} = $name; -} - -# Now make a list of .mod files in the file_paths. If a .o source dependency -# can't be found based on the module_files list above, then maybe a .mod -# module dependency can if the mod file is visible. -my %trumod_files = (); -my ($dir); -my ($f, $name, $path, $suffix, $mod); -my @suffixes = ('\.mod' ); -foreach $dir (@file_paths) { - @filenames = (bsd_glob("$dir/*.mod")); - foreach $f (@filenames) { - ($name, $path, $suffix) = fileparse($f, @suffixes); - ($mod = $name) =~ tr/a-z/A-Z/; - $trumod_files{$mod} = $name; - } -} - -#print STDERR "\%module_files\n"; -#while ( ($k,$v) = each %module_files ) { -# print STDERR "$k => $v\n"; -#} - -# Find module and include dependencies of the source files. -my ($file_path, $rmods, $rincs); -my %file_modules = (); -my %file_includes = (); -my @check_includes = (); -foreach $f ( @src ) { - - # Find the file in the seach path (@file_paths). - unless ($file_path = find_file($f)) { - if (defined $opt{'w'}) {print STDERR "$f not found\n";} - next; - } - - # Find the module and include dependencies. - ($rmods, $rincs) = find_dependencies( $file_path ); - - # Remove redundancies (a file can contain multiple procedures that have - # the same dependencies). - $file_modules{$f} = rm_duplicates($rmods); - $file_includes{$f} = rm_duplicates($rincs); - - # Make a list of all include files. - push @check_includes, @{$file_includes{$f}}; -} - -#print STDERR "\%file_modules\n"; -#while ( ($k,$v) = each %file_modules ) { -# print STDERR "$k => @$v\n"; -#} -#print STDERR "\%file_includes\n"; -#while ( ($k,$v) = each %file_includes ) { -# print STDERR "$k => @$v\n"; -#} -#print STDERR "\@check_includes\n"; -#print STDERR "@check_includes\n"; - -# Find include file dependencies. -my %include_depends = (); -while (@check_includes) { - $f = shift @check_includes; - if (defined($include_depends{$f})) { next; } - - # Mark files not in path so they can be removed from the dependency list. - unless ($file_path = find_file($f)) { - $include_depends{$f} = -1; - next; - } - - # Find include file dependencies. - ($rmods, $include_depends{$f}) = find_dependencies($file_path); - - # Add included include files to the back of the check_includes list so - # that their dependencies can be found. - push @check_includes, @{$include_depends{$f}}; - - # Add included modules to the include_depends list. - if ( @$rmods ) { push @{$include_depends{$f}}, @$rmods; } -} - -#print STDERR "\%include_depends\n"; -#while ( ($k,$v) = each %include_depends ) { -# print STDERR (ref $v ? "$k => @$v\n" : "$k => $v\n"); -#} - -# Remove include file dependencies that are not in the Filepath. -my $i, $ii; -foreach $f (keys %include_depends) { - - unless (ref $include_depends{$f}) { next; } - $rincs = $include_depends{$f}; - unless (@$rincs) { next; } - $ii = 0; - $num_incs = @$rincs; - for ($i = 0; $i < $num_incs; ++$i) { - if ($include_depends{$$rincs[$ii]} == -1) { - splice @$rincs, $ii, 1; - next; - } - ++$ii; - } -} - -# Substitute the include file dependencies into the %file_includes lists. -foreach $f (keys %file_includes) { - my @expand_incs = (); - - # Initialize the expanded %file_includes list. - my $i; - unless (@{$file_includes{$f}}) { next; } - foreach $i (@{$file_includes{$f}}) { - push @expand_incs, $i unless ($include_depends{$i} == -1); - } - unless (@expand_incs) { - $file_includes{$f} = []; - next; - } - - # Expand - for ($i = 0; $i <= $#expand_incs; ++$i) { - push @expand_incs, @{ $include_depends{$expand_incs[$i]} }; - } - - $file_includes{$f} = rm_duplicates(\@expand_incs); -} - -#print STDERR "expanded \%file_includes\n"; -#while ( ($k,$v) = each %file_includes ) { -# print STDERR "$k => @$v\n"; -#} - -# Print dependencies to STDOUT. -foreach $f (sort keys %file_modules) { - $f =~ /(.+)\./; - $target = "$1.o"; - if ( defined $opt{'t'} ) { $target = "$opt{'t'}/$1.o"; } - print "$target : $f @{$file_modules{$f}} @{$file_includes{$f}}\n"; -} - -#-------------------------------------------------------------------------------------- - -sub find_dependencies { - - # Find dependencies of input file. - # Use'd Fortran 90 modules are returned in \@mods. - # Files that are "#include"d by the cpp preprocessor are returned in \@incs. - - my( $file ) = @_; - my( @mods, @incs ); - - open(FH, $file) or die "Can't open $file: $!\n"; - - while ( ) { - # Search for "#include" and strip filename when found. - if ( /^#include\s+[<"](.*)[>"]/ ) { - push @incs, $1; - } - # Search for Fortran include dependencies. - elsif ( /^\s*include\s+['"](.*)['"]/ ) { #" for emacs fontlock - push @incs, $1; - } - # Search for module dependencies. - elsif ( /^\s*USE\s+(\w+)/i ) { - ($module = $1) =~ tr/a-z/A-Z/; - # Return dependency in the form of a .o version of the file that contains - # the module. this is from the source list. - if ( defined $module_files{$module} ) { - if ( defined $obj_dir ) { - push @mods, "$obj_dir/$module_files{$module}.o"; - } else { - push @mods, "$module_files{$module}.o"; - } - } - # Return dependency in the form of a .mod version of the file that contains - # the module. this is from the .mod list. only if .o version not found - elsif ( defined $trumod_files{$module} ) { - if ( defined $obj_dir ) { - push @mods, "$obj_dir/$trumod_files{$module}.mod"; - } else { - push @mods, "$trumod_files{$module}.mod"; - } - } - } - } - close( FH ); - return (\@mods, \@incs); -} - -#-------------------------------------------------------------------------------------- - -sub find_file { - -# Search for the specified file in the list of directories in the global -# array @file_paths. Return the first occurance found, or the null string if -# the file is not found. - - my($file) = @_; - my($dir, $fname); - - foreach $dir (@file_paths) { - $fname = "$dir/$file"; - if ( -f $fname ) { return $fname; } - } - return ''; # file not found -} - -#-------------------------------------------------------------------------------------- - -sub rm_duplicates { - -# Return a list with duplicates removed. - - my ($in) = @_; # input arrary reference - my @out = (); - my $i; - my %h = (); - foreach $i (@$in) { - $h{$i} = ''; - } - @out = keys %h; - return \@out; -} - -#-------------------------------------------------------------------------------------- - -sub usage { - ($ProgName = $0) =~ s!.*/!!; # name of program - die <abort if file not found 1=>do not abort -! -! !REVISION HISTORY: -! Created by Mariana Vertenstein -! -! -! !LOCAL VARIABLES: -!EOP - integer i !loop index - integer klen !length of fulpath character string - logical lexist !true if local file exists -!------------------------------------------------------------------------ - - ! get local file name from full name - - locfn = get_filename( fulpath ) - if (len_trim(locfn) == 0) then - write(iulog,*)'(GETFIL): local filename has zero length' - call shr_sys_abort - else - write(iulog,*)'(GETFIL): attempting to find local file ', & - trim(locfn) - endif - - ! first check if file is in current working directory. - - inquire (file=locfn,exist=lexist) - if (lexist) then - write(iulog,*) '(GETFIL): using ',trim(locfn), & - ' in current working directory' - RETURN - endif - - ! second check for full pathname on disk - locfn = fulpath - - inquire (file=fulpath,exist=lexist) - if (lexist) then - write(iulog,*) '(GETFIL): using ',trim(fulpath) - RETURN - else - write(iulog,*)'(GETFIL): failed getting file from full path: ', fulpath - if (present(iflag) .and. iflag==0) then - call shr_sys_abort ('GETFIL: FAILED to get '//trim(fulpath)) - else - RETURN - endif - endif - - end subroutine getfil - -!------------------------------------------------------------------------ -!BOP -! -! !IROUTINE: opnfil -! -! !INTERFACE: - subroutine opnfil (locfn, iun, form) -! -! !DESCRIPTION: -! Open file locfn in unformatted or formatted form on unit iun -! -! !ARGUMENTS: -! - implicit none - character(len=*), intent(in):: locfn !file name - integer, intent(in):: iun !fortran unit number - character(len=1), intent(in):: form !file format: u = unformatted, - !f = formatted -! -! !REVISION HISTORY: -! Created by Mariana Vertenstein -! -! -! !LOCAL VARIABLES: -!EOP - integer ioe !error return from fortran open - character(len=11) ft !format type: formatted. unformatted -!------------------------------------------------------------------------ - - if (len_trim(locfn) == 0) then - write(iulog,*)'(OPNFIL): local filename has zero length' - call shr_sys_abort - endif - if (form=='u' .or. form=='U') then - ft = 'unformatted' - else - ft = 'formatted ' - end if - open (unit=iun,file=locfn,status='unknown',form=ft,iostat=ioe) - if (ioe /= 0) then - write(iulog,*)'(OPNFIL): failed to open file ',trim(locfn), & - & ' on unit ',iun,' ierr=',ioe - call shr_sys_abort - else - write(iulog,*)'(OPNFIL): Successfully opened file ',trim(locfn), & - & ' on unit= ',iun - end if - - end subroutine opnfil - -!------------------------------------------------------------------------ -!BOP -! -! !IROUTINE: getavu -! -! !INTERFACE: - integer function getavu() -! -! !DESCRIPTION: -! Get next available Fortran unit number. -! -! !USES: - use shr_file_mod, only : shr_file_getUnit -! -! !ARGUMENTS: - implicit none -! -! !REVISION HISTORY: -! Created by Gordon Bonan -! Modified for clm2 by Mariana Vertenstein -! -! -! !LOCAL VARIABLES: -!EOP -!------------------------------------------------------------------------ - - getavu = shr_file_getunit() - - end function getavu - -!------------------------------------------------------------------------ -!BOP -! -! !IROUTINE: relavu -! -! !INTERFACE: - subroutine relavu (iunit) -! -! !DESCRIPTION: -! Close and release Fortran unit no longer in use! -! -! !USES: - use shr_file_mod, only : shr_file_freeUnit -! -! !ARGUMENTS: - implicit none - integer, intent(in) :: iunit !Fortran unit number -! -! !REVISION HISTORY: -! Created by Gordon Bonan -! -!EOP -!------------------------------------------------------------------------ - - close(iunit) - call shr_file_freeUnit(iunit) - - end subroutine relavu - -end module fileutils diff --git a/tools/mksurfdata_map/src/mkVICparamsMod.F90 b/tools/mksurfdata_map/src/mkVICparamsMod.F90 deleted file mode 100644 index 431e43cb28..0000000000 --- a/tools/mksurfdata_map/src/mkVICparamsMod.F90 +++ /dev/null @@ -1,200 +0,0 @@ -module mkVICparamsMod - -!----------------------------------------------------------------------- -!BOP -! -! !MODULE: mkVICparamsMod -! -! !DESCRIPTION: -! make parameters for VIC -! -! !REVISION HISTORY: -! Author: Bill Sacks -! -!----------------------------------------------------------------------- -! -! !USES: - use shr_kind_mod, only : r8 => shr_kind_r8 - use shr_sys_mod , only : shr_sys_flush - use mkdomainMod , only : domain_checksame - - implicit none - - private - -! !PUBLIC MEMBER FUNCTIONS: - public mkVICparams ! make VIC parameters -! -!EOP -!=============================================================== -contains -!=============================================================== - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: mkVICparams -! -! !INTERFACE: -subroutine mkVICparams(ldomain, mapfname, datfname, ndiag, & - binfl_o, ws_o, dsmax_o, ds_o) -! -! !DESCRIPTION: -! make VIC parameters -! -! !USES: - use mkdomainMod, only : domain_type, domain_clean, domain_read - use mkgridmapMod - use mkncdio - use mkdiagnosticsMod, only : output_diagnostics_continuous - use mkchecksMod, only : min_bad -! -! !ARGUMENTS: - - implicit none - type(domain_type) , intent(in) :: ldomain - character(len=*) , intent(in) :: mapfname ! input mapping file name - character(len=*) , intent(in) :: datfname ! input data file name - integer , intent(in) :: ndiag ! unit number for diag out - real(r8) , intent(out):: binfl_o(:) ! output grid: VIC b parameter for the Variable Infiltration Capacity Curve (unitless) - real(r8) , intent(out):: ws_o(:) ! output grid: VIC Ws parameter for the ARNO curve (unitless) - real(r8) , intent(out):: dsmax_o(:) ! output grid: VIC Dsmax parameter for the ARNO curve (mm/day) - real(r8) , intent(out):: ds_o(:) ! output grid: VIC Ds parameter for the ARNO curve (unitless) -! -! !CALLED FROM: -! subroutine mksrfdat in module mksrfdatMod -! -! !REVISION HISTORY: -! Author: Bill Sacks -! -! -! !LOCAL VARIABLES: -!EOP - type(gridmap_type) :: tgridmap - type(domain_type) :: tdomain ! local domain - real(r8), allocatable :: data_i(:) ! data on input grid - real(r8), allocatable :: frac_dst(:) ! output fractions - real(r8), allocatable :: mask_r8(:) ! float of tdomain%mask - integer :: ncid,varid ! input netCDF id's - integer :: ier ! error status - - real(r8), parameter :: min_valid_binfl = 0._r8 - real(r8), parameter :: min_valid_ws = 0._r8 - real(r8), parameter :: min_valid_dsmax = 0._r8 - real(r8), parameter :: min_valid_ds = 0._r8 - - character(len=32) :: subname = 'mkVICparams' -!----------------------------------------------------------------------- - - write (6,*) 'Attempting to make VIC parameters.....' - call shr_sys_flush(6) - - ! ----------------------------------------------------------------- - ! Read domain and mapping information, check for consistency - ! ----------------------------------------------------------------- - - call domain_read(tdomain,datfname) - - call gridmap_mapread(tgridmap, mapfname ) - - ! Obtain frac_dst - allocate(frac_dst(ldomain%ns), stat=ier) - if (ier/=0) call abort() - call gridmap_calc_frac_dst(tgridmap, tdomain%mask, frac_dst) - - allocate(mask_r8(tdomain%ns), stat=ier) - if (ier/=0) call abort() - mask_r8 = tdomain%mask - call gridmap_check( tgridmap, mask_r8, frac_dst, subname ) - - call domain_checksame( tdomain, ldomain, tgridmap ) - - ! ----------------------------------------------------------------- - ! Open input file, allocate memory for input data - ! ----------------------------------------------------------------- - - write(6,*)'Open VIC parameter file: ', trim(datfname) - call check_ret(nf_open(datfname, 0, ncid), subname) - - allocate(data_i(tdomain%ns), stat=ier) - if (ier/=0) call abort() - - ! ----------------------------------------------------------------- - ! Regrid binfl - ! ----------------------------------------------------------------- - - call check_ret(nf_inq_varid (ncid, 'binfl', varid), subname) - call check_ret(nf_get_var_double (ncid, varid, data_i), subname) - call gridmap_areaave_srcmask(tgridmap, data_i, binfl_o, nodata=0.1_r8, mask_src=tdomain%mask, frac_dst=frac_dst) - - ! Check validity of output data - if (min_bad(binfl_o, min_valid_binfl, 'binfl')) then - call abort() - end if - - call output_diagnostics_continuous(data_i, binfl_o, tgridmap, "VIC b parameter", "unitless", ndiag, tdomain%mask, frac_dst) - - ! ----------------------------------------------------------------- - ! Regrid Ws - ! ----------------------------------------------------------------- - - call check_ret(nf_inq_varid (ncid, 'Ws', varid), subname) - call check_ret(nf_get_var_double (ncid, varid, data_i), subname) - call gridmap_areaave_srcmask(tgridmap, data_i, ws_o, nodata=0.75_r8, mask_src=tdomain%mask, frac_dst=frac_dst) - - ! Check validity of output data - if (min_bad(ws_o, min_valid_ws, 'Ws')) then - call abort() - end if - - call output_diagnostics_continuous(data_i, ws_o, tgridmap, "VIC Ws parameter", "unitless", ndiag, tdomain%mask, frac_dst) - - ! ----------------------------------------------------------------- - ! Regrid Dsmax - ! ----------------------------------------------------------------- - - call check_ret(nf_inq_varid (ncid, 'Dsmax', varid), subname) - call check_ret(nf_get_var_double (ncid, varid, data_i), subname) - call gridmap_areaave_srcmask(tgridmap, data_i, dsmax_o, nodata=10._r8, mask_src=tdomain%mask, frac_dst=frac_dst) - - ! Check validity of output data - if (min_bad(dsmax_o, min_valid_dsmax, 'Dsmax')) then - call abort() - end if - - call output_diagnostics_continuous(data_i, dsmax_o, tgridmap, "VIC Dsmax parameter", "mm/day", ndiag, tdomain%mask, frac_dst) - - ! ----------------------------------------------------------------- - ! Regrid Ds - ! ----------------------------------------------------------------- - - call check_ret(nf_inq_varid (ncid, 'Ds', varid), subname) - call check_ret(nf_get_var_double (ncid, varid, data_i), subname) - call gridmap_areaave_srcmask(tgridmap, data_i, ds_o, nodata=0.1_r8, mask_src=tdomain%mask, frac_dst=frac_dst) - - ! Check validity of output data - if (min_bad(ds_o, min_valid_ds, 'Ds')) then - call abort() - end if - - call output_diagnostics_continuous(data_i, ds_o, tgridmap, "VIC Ds parameter", "unitless", ndiag, tdomain%mask, frac_dst) - - ! ----------------------------------------------------------------- - ! Close files and deallocate dynamic memory - ! ----------------------------------------------------------------- - - call check_ret(nf_close(ncid), subname) - call domain_clean(tdomain) - call gridmap_clean(tgridmap) - deallocate (data_i) - deallocate (frac_dst) - deallocate (mask_r8) - - write (6,*) 'Successfully made VIC parameters' - write (6,*) - call shr_sys_flush(6) - -end subroutine mkVICparams - - -end module mkVICparamsMod diff --git a/tools/mksurfdata_map/src/mkagfirepkmonthMod.F90 b/tools/mksurfdata_map/src/mkagfirepkmonthMod.F90 deleted file mode 100644 index 7b58ddffad..0000000000 --- a/tools/mksurfdata_map/src/mkagfirepkmonthMod.F90 +++ /dev/null @@ -1,273 +0,0 @@ -module mkagfirepkmonthMod -!----------------------------------------------------------------------- -!BOP -! -! !MODULE: mkagfirepkmonthMod -! -! !DESCRIPTION: -! Make agricultural fire peak month data -! -! !REVISION HISTORY: -! Author: Sam Levis and Bill Sacks -! -!----------------------------------------------------------------------- -!!USES: - use shr_kind_mod, only : r8 => shr_kind_r8 - use shr_sys_mod , only : shr_sys_flush - use mkdomainMod , only : domain_checksame - implicit none - - SAVE - private ! By default make data private -! -! !PUBLIC MEMBER FUNCTIONS: -! - public mkagfirepkmon ! Set agricultural fire peak month -! -! !PRIVATE MEMBER FUNCTIONS: - private define_months ! define month strings -! -! !PRIVATE DATA MEMBERS: -! - integer , parameter :: min_valid_value = 1 - integer , parameter :: max_valid_value = 12 - integer , parameter :: unsetmon = 13 ! flag to indicate agricultural fire peak month NOT set -! -! !PRIVATE DATA MEMBERS: -! -!EOP -!=============================================================== -contains -!=============================================================== - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: mkagfirepkmon -! -! !INTERFACE: -subroutine mkagfirepkmon(ldomain, mapfname, datfname, ndiag, & - agfirepkmon_o) -! -! !DESCRIPTION: -! Make agricultural fire peak month data from higher resolution data -! -! !USES: - use mkdomainMod, only : domain_type, domain_clean, domain_read - use mkgridmapMod - use mkindexmapMod, only : get_dominant_indices - use mkvarpar, only : re - use mkncdio - use mkchecksMod, only : min_bad, max_bad -! -! !ARGUMENTS: - implicit none - type(domain_type) , intent(in) :: ldomain - character(len=*) , intent(in) :: mapfname ! input mapping file name - character(len=*) , intent(in) :: datfname ! input data file name - integer , intent(in) :: ndiag ! unit number for diag out - integer , intent(out):: agfirepkmon_o(:) ! agricultural fire peak month -! -! !CALLED FROM: -! subroutine mksrfdat in module mksrfdatMod -! -! !REVISION HISTORY: -! Author: Sam Levis and Bill Sacks -! -! -! !LOCAL VARIABLES: -!EOP - type(gridmap_type) :: tgridmap - type(domain_type) :: tdomain ! local domain - real(r8), allocatable :: gast_i(:) ! global area, by surface type - real(r8), allocatable :: gast_o(:) ! global area, by surface type - real(r8), allocatable :: frac_dst(:) ! output fractions - real(r8), allocatable :: mask_r8(:) ! float of tdomain%mask - integer , allocatable :: agfirepkmon_i(:) ! input grid: agricultural fire peak month - integer :: nagfirepkmon ! number of peak months - character(len=35), allocatable :: month(:)! name of each month - integer :: k,ni,no,ns_i,ns_o ! indices - integer :: ncid,varid ! input netCDF id's - integer :: ier ! error status - - integer, parameter :: miss = unsetmon ! missing data indicator - integer, parameter :: min_valid = 1 ! minimum valid value - integer, parameter :: max_valid = 13 ! maximum valid value - character(len=32) :: subname = 'mkagfirepkmon' -!----------------------------------------------------------------------- - - write (6,*) 'Attempting to make agricultural fire peak month data .....' - call shr_sys_flush(6) - - ! ----------------------------------------------------------------- - ! Read domain and mapping information, check for consistency - ! ----------------------------------------------------------------- - - call domain_read( tdomain,datfname ) - - call gridmap_mapread( tgridmap, mapfname ) - - ! Obtain frac_dst - ns_o = ldomain%ns - allocate(frac_dst(ns_o), stat=ier) - if (ier/=0) call abort() - call gridmap_calc_frac_dst(tgridmap, tdomain%mask, frac_dst) - - ns_i = tdomain%ns - allocate(mask_r8(ns_i), stat=ier) - if (ier/=0) call abort() - mask_r8 = tdomain%mask - call gridmap_check( tgridmap, mask_r8, frac_dst, subname ) - - call domain_checksame( tdomain, ldomain, tgridmap ) - - ! ----------------------------------------------------------------- - ! Open input file, allocate memory for input data - ! ----------------------------------------------------------------- - - write (6,*) 'Open agricultural fire peak month file: ', trim(datfname) - call check_ret(nf_open(datfname, 0, ncid), subname) - - allocate(agfirepkmon_i(ns_i), stat=ier) - if (ier/=0) call abort() - - ! ----------------------------------------------------------------- - ! Regrid ag fire peak month - ! ----------------------------------------------------------------- - - call check_ret(nf_inq_varid (ncid, 'abm', varid), subname) - call check_ret(nf_get_var_int (ncid, varid, agfirepkmon_i), subname) - ! Note that any input point that is outside the range [min_valid_value,max_valid_value] - ! will be ignored; this ignores input points with value of unsetmon - call get_dominant_indices(tgridmap, agfirepkmon_i, agfirepkmon_o, & - min_valid_value, max_valid_value, miss, mask_src=tdomain%mask) - - ! Check validity of output data - if (min_bad(agfirepkmon_o, min_valid, 'agfirepkmon') .or. & - max_bad(agfirepkmon_o, max_valid, 'agfirepkmon')) then - call abort() - end if - - - ! ----------------------------------------------------------------- - ! Output diagnostics comparing global area of each peak month on input and output grids - ! - ! WJS (3-4-13): I am trying to generally put these diagnostics in mkdiagnosticsMod, but - ! so far there isn't a general diagnostics routine for categorical data - ! - ! TODO(wjs, 2016-01-22) Now there is a routine for this: output_diagnostics_index. - ! However, it currently doesn't provide the capability for named months. Either add - ! that capability or decide it's not important, then delete the below code, instead - ! calling output_diagnostics_index. - ! ----------------------------------------------------------------- - - nagfirepkmon = maxval(agfirepkmon_i) - allocate(gast_i(1:nagfirepkmon),gast_o(1:nagfirepkmon),month(1:nagfirepkmon)) - call define_months(nagfirepkmon, month) - - gast_i(:) = 0.0_r8 - do ni = 1,ns_i - k = agfirepkmon_i(ni) - gast_i(k) = gast_i(k) + tgridmap%area_src(ni)*tdomain%mask(ni)*re**2 - end do - - gast_o(:) = 0.0_r8 - do no = 1,ns_o - k = agfirepkmon_o(no) - gast_o(k) = gast_o(k) + tgridmap%area_dst(no)*frac_dst(no)*re**2 - end do - - ! area comparison - - write (ndiag,*) - write (ndiag,'(1x,70a1)') ('=',k=1,70) - write (ndiag,*) 'Agricultural fire peak month Output' - write (ndiag,'(1x,70a1)') ('=',k=1,70) - - write (ndiag,*) - write (ndiag,'(1x,70a1)') ('.',k=1,70) - write (ndiag,1001) -1001 format (1x,'peak month',20x,' input grid area output grid area',/ & - 1x,33x,' 10**6 km**2',' 10**6 km**2') - write (ndiag,'(1x,70a1)') ('.',k=1,70) - write (ndiag,*) - - do k = 1, nagfirepkmon - write (ndiag,1002) month(k),gast_i(k)*1.e-6,gast_o(k)*1.e-6 -1002 format (1x,a35,f16.3,f17.3) - end do - - ! ----------------------------------------------------------------- - ! Close files and deallocate dynamic memory - ! ----------------------------------------------------------------- - - call check_ret(nf_close(ncid), subname) - call domain_clean(tdomain) - call gridmap_clean(tgridmap) - deallocate (agfirepkmon_i,gast_i,gast_o,month, frac_dst, mask_r8) - - write (6,*) 'Successfully made Agricultural fire peak month' - write (6,*) - call shr_sys_flush(6) - -end subroutine mkagfirepkmon - -!----------------------------------------------------------------------- - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: define_months -! -! !INTERFACE: -subroutine define_months(nagfirepkmon, month) -! -! !DESCRIPTION: -! Define month strings -! -! !USES: -! -! !ARGUMENTS: - implicit none - integer , intent(in) :: nagfirepkmon ! max input value (including the 'unset' special value) - character(len=*), intent(out):: month(:) ! name of each month value -! -! !CALLED FROM: -! subroutine mkagfirepkmon -! -! !REVISION HISTORY: -! Author: Bill Sacks -! -! -! !LOCAL VARIABLES: -!EOP -!----------------------------------------------------------------------- - - if (nagfirepkmon == unsetmon) then - if (size(month) < 13) then - write(6,*) 'month array too small: ', size(month), ' < 13' - call abort() - end if - month(1) = 'January ' - month(2) = 'February ' - month(3) = 'March ' - month(4) = 'April ' - month(5) = 'May ' - month(6) = 'June ' - month(7) = 'July ' - month(8) = 'August ' - month(9) = 'September ' - month(10) = 'October ' - month(11) = 'November ' - month(12) = 'December ' - month(13) = 'no agricultural fire peak month data' - else - write(6,*)'nagfirepkmon value of ',nagfirepkmon,' not supported' - call abort() - end if - -end subroutine define_months -!----------------------------------------------------------------------- - - -end module mkagfirepkmonthMod diff --git a/tools/mksurfdata_map/src/mkchecksMod.F90 b/tools/mksurfdata_map/src/mkchecksMod.F90 deleted file mode 100644 index 94b8fe5930..0000000000 --- a/tools/mksurfdata_map/src/mkchecksMod.F90 +++ /dev/null @@ -1,233 +0,0 @@ -module mkchecksMod -!----------------------------------------------------------------------- -!BOP -! -! !MODULE: mkchecks -! -! !DESCRIPTION: -! Generic routines to check validity of output fields -! -! -! !USES: - use shr_kind_mod, only : r8 => shr_kind_r8 - use shr_sys_mod , only : shr_sys_flush - - implicit none - private -! -! !PUBLIC MEMBER FUNCTIONS: - public :: min_bad ! check the minimum value of a field - public :: max_bad ! check the maximum value of a field - - interface min_bad - module procedure min_bad_int - module procedure min_bad_r8 - end interface min_bad - - interface max_bad - module procedure max_bad_int - module procedure max_bad_r8 - end interface max_bad -! -! -! !REVISION HISTORY: -! Author: Bill Sacks -! -!EOP -!------------------------------------------------------------------------------ -contains - -!------------------------------------------------------------------------------ -!BOP -! -! !IROUTINE: min_bad_r8 -! -! !INTERFACE: -logical function min_bad_r8(data, min_allowed, varname) -! -! !DESCRIPTION: -! Confirm that no value of data is less than min_allowed. -! Returns true if errors found, false otherwise. -! Also prints offending points -! -! -! !USES: -! -! !ARGUMENTS: - implicit none - real(r8) , intent(in) :: data(:) ! array of data to check - real(r8) , intent(in) :: min_allowed ! minimum valid value - character(len=*) , intent(in) :: varname ! name of field -! -! !REVISION HISTORY: -! Author: Bill Sacks -! -! -! !LOCAL VARIABLES: -!EOP - logical :: errors_found ! true if any errors have been found - integer :: n ! index - - character(len=*), parameter :: subname = 'min_bad_r8' -!------------------------------------------------------------------------------ - - errors_found = .false. - - do n = 1, size(data) - if (data(n) < min_allowed) then - write(6,*) subname//' ERROR: ', trim(varname), ' = ', data(n), ' less than ',& - min_allowed, ' at ', n - errors_found = .true. - end if - end do - - call shr_sys_flush(6) - min_bad_r8 = errors_found -end function min_bad_r8 - -!------------------------------------------------------------------------------ -!BOP -! -! !IROUTINE: min_bad_int -! -! !INTERFACE: -logical function min_bad_int(data, min_allowed, varname) -! -! !DESCRIPTION: -! Confirm that no value of data is less than min_allowed. -! Returns true if errors found, false otherwise. -! Also prints offending points -! -! -! !USES: -! -! !ARGUMENTS: - implicit none - integer , intent(in) :: data(:) ! array of data to check - integer , intent(in) :: min_allowed ! minimum valid value - character(len=*) , intent(in) :: varname ! name of field -! -! !REVISION HISTORY: -! Author: Bill Sacks -! -! -! !LOCAL VARIABLES: -!EOP - logical :: errors_found ! true if any errors have been found - integer :: n ! index - - character(len=*), parameter :: subname = 'min_bad_int' -!------------------------------------------------------------------------------ - - errors_found = .false. - - do n = 1, size(data) - if (data(n) < min_allowed) then - write(6,*) subname//' ERROR: ', trim(varname), ' = ', data(n), ' less than ',& - min_allowed, ' at ', n - errors_found = .true. - end if - end do - - call shr_sys_flush(6) - min_bad_int = errors_found -end function min_bad_int - -!------------------------------------------------------------------------------ -!BOP -! -! !IROUTINE: max_bad_r8 -! -! !INTERFACE: -logical function max_bad_r8(data, max_allowed, varname) -! -! !DESCRIPTION: -! Confirm that no value of data is greate than max_allowed. -! Returns true if errors found, false otherwise. -! Also prints offending points -! -! -! !USES: -! -! !ARGUMENTS: - implicit none - real(r8) , intent(in) :: data(:) ! array of data to check - real(r8) , intent(in) :: max_allowed ! maximum valid value - character(len=*) , intent(in) :: varname ! name of field -! -! !REVISION HISTORY: -! Author: Bill Sacks -! -! -! !LOCAL VARIABLES: -!EOP - logical :: errors_found ! true if any errors have been found - integer :: n ! index - - character(len=*), parameter :: subname = 'max_bad_r8' -!------------------------------------------------------------------------------ - - errors_found = .false. - - do n = 1, size(data) - if (data(n) > max_allowed) then - write(6,*) subname//' ERROR: ', trim(varname), ' = ', data(n), ' greater than ',& - max_allowed, ' at ', n - errors_found = .true. - end if - end do - - call shr_sys_flush(6) - max_bad_r8 = errors_found -end function max_bad_r8 - -!------------------------------------------------------------------------------ -!BOP -! -! !IROUTINE: max_bad_int -! -! !INTERFACE: -logical function max_bad_int(data, max_allowed, varname) -! -! !DESCRIPTION: -! Confirm that no value of data is greate than max_allowed. -! Returns true if errors found, false otherwise. -! Also prints offending points -! -! -! !USES: -! -! !ARGUMENTS: - implicit none - integer , intent(in) :: data(:) ! array of data to check - integer , intent(in) :: max_allowed ! maximum valid value - character(len=*) , intent(in) :: varname ! name of field -! -! !REVISION HISTORY: -! Author: Bill Sacks -! -! -! !LOCAL VARIABLES: -!EOP - logical :: errors_found ! true if any errors have been found - integer :: n ! index - - character(len=*), parameter :: subname = 'max_bad_int' -!------------------------------------------------------------------------------ - - errors_found = .false. - - do n = 1, size(data) - if (data(n) > max_allowed) then - write(6,*) subname//' ERROR: ', trim(varname), ' = ', data(n), ' greater than ',& - max_allowed, ' at ', n - errors_found = .true. - end if - end do - - call shr_sys_flush(6) - max_bad_int = errors_found -end function max_bad_int - - -end module mkchecksMod diff --git a/tools/mksurfdata_map/src/mkdiagnosticsMod.F90 b/tools/mksurfdata_map/src/mkdiagnosticsMod.F90 deleted file mode 100644 index 91769a5823..0000000000 --- a/tools/mksurfdata_map/src/mkdiagnosticsMod.F90 +++ /dev/null @@ -1,452 +0,0 @@ -module mkdiagnosticsMod -!----------------------------------------------------------------------- -!BOP -! -! !MODULE: mkdiagnostics -! -! !DESCRIPTION: -! Output diagnostics to log file -! -! -! !USES: - use shr_kind_mod, only : r8 => shr_kind_r8 - - implicit none - private -! -! !PUBLIC MEMBER FUNCTIONS: - public :: output_diagnostics_area ! output diagnostics for field that is % of grid area - public :: output_diagnostics_continuous ! output diagnostics for a continuous (real-valued) field - public :: output_diagnostics_continuous_outonly ! output diagnostics for a continuous (real-valued) field, just on the output grid - public :: output_diagnostics_index ! output diagnostics for an index field -! -! -! !REVISION HISTORY: -! Author: Bill Sacks -! -!EOP -!------------------------------------------------------------------------------ -contains - -!------------------------------------------------------------------------------ -!BOP -! -! !IROUTINE: output_diagnostics_area -! -! !INTERFACE: -subroutine output_diagnostics_area(data_i, data_o, gridmap, name, percent, ndiag, mask_src, frac_dst) -! -! !DESCRIPTION: -! Output diagnostics for a field that gives either fraction or percent of grid cell area -! -! !USES: - use mkgridmapMod, only : gridmap_type - use mkvarpar, only : re -! -! !ARGUMENTS: - implicit none - real(r8) , intent(in) :: data_i(:) ! data on input grid - real(r8) , intent(in) :: data_o(:) ! data on output grid - type(gridmap_type), intent(in) :: gridmap ! mapping info - character(len=*) , intent(in) :: name ! name of field - logical , intent(in) :: percent ! is field specified as percent? (alternative is fraction) - integer , intent(in) :: ndiag ! unit number for diagnostic output - integer, intent(in) :: mask_src(:) - real(r8), intent(in) :: frac_dst(:) -! -! !REVISION HISTORY: -! Author: Bill Sacks -! -! -! !LOCAL VARIABLES: -!EOP - real(r8) :: gdata_i ! global sum of input data - real(r8) :: gdata_o ! global sum of output data - real(r8) :: garea_i ! global sum of input area - real(r8) :: garea_o ! global sum of output area - integer :: ns_i, ns_o ! sizes of input & output grids - integer :: ni,no,k ! indices - - character(len=*), parameter :: subname = "output_diagnostics_area" -!------------------------------------------------------------------------------ - - ! Error check for array size consistencies - - ns_i = gridmap%na - ns_o = gridmap%nb - if (size(data_i) /= ns_i .or. & - size(data_o) /= ns_o) then - write(6,*) subname//' ERROR: array size inconsistencies for ', trim(name) - write(6,*) 'size(data_i) = ', size(data_i) - write(6,*) 'ns_i = ', ns_i - write(6,*) 'size(data_o) = ', size(data_o) - write(6,*) 'ns_o = ', ns_o - call abort() - end if - if (size(frac_dst) /= ns_o) then - write(6,*) subname//' ERROR: incorrect size of frac_dst' - write(6,*) 'size(frac_dst) = ', size(frac_dst) - write(6,*) 'ns_o = ', ns_o - call abort() - end if - if (size(mask_src) /= ns_i) then - write(6,*) subname//' ERROR: incorrect size of mask_src' - write(6,*) 'size(mask_src) = ', size(mask_src) - write(6,*) 'ns_i = ', ns_i - call abort() - end if - - ! Sums on input grid - - gdata_i = 0. - garea_i = 0. - do ni = 1,ns_i - garea_i = garea_i + gridmap%area_src(ni)*re**2 - gdata_i = gdata_i + data_i(ni) * gridmap%area_src(ni) * mask_src(ni) * re**2 - end do - - ! Sums on output grid - - gdata_o = 0. - garea_o = 0. - do no = 1,ns_o - garea_o = garea_o + gridmap%area_dst(no)*re**2 - gdata_o = gdata_o + data_o(no) * gridmap%area_dst(no) * frac_dst(no) * re**2 - end do - - ! Correct units - - if (percent) then - gdata_i = gdata_i / 100._r8 - gdata_o = gdata_o / 100._r8 - end if - - ! Diagnostic output - - write (ndiag,*) - write (ndiag,'(1x,70a1)') ('=',k=1,70) - write (ndiag,*) trim(name), ' Output' - write (ndiag,'(1x,70a1)') ('=',k=1,70) - - write (ndiag,*) - write (ndiag,'(1x,70a1)') ('.',k=1,70) - write (ndiag,2001) -2001 format (1x,'surface type input grid area output grid area'/ & - 1x,' 10**6 km**2 10**6 km**2 ') - write (ndiag,'(1x,70a1)') ('.',k=1,70) - write (ndiag,*) - write (ndiag,2002) name, gdata_i*1.e-06, gdata_o*1.e-06 - write (ndiag,2002) 'all surface', garea_i*1.e-06, garea_o*1.e-06 -2002 format (1x,a12, f14.3,f17.3) - -end subroutine output_diagnostics_area -!------------------------------------------------------------------------------ - -!------------------------------------------------------------------------------ -!BOP -! -! !IROUTINE: output_diagnostics_continuous -! -! !INTERFACE: -subroutine output_diagnostics_continuous(data_i, data_o, gridmap, name, units, ndiag, mask_src, frac_dst) -! -! !DESCRIPTION: -! Output diagnostics for a continuous field (but not area, for which there is a different routine) -! -! !USES: - use mkgridmapMod, only : gridmap_type - use mkvarpar, only : re -! -! !ARGUMENTS: - implicit none - real(r8) , intent(in) :: data_i(:) ! data on input grid - real(r8) , intent(in) :: data_o(:) ! data on output grid - type(gridmap_type), intent(in) :: gridmap ! mapping info - character(len=*) , intent(in) :: name ! name of field - character(len=*) , intent(in) :: units ! units of field - integer , intent(in) :: ndiag ! unit number for diagnostic output - integer, intent(in) :: mask_src(:) - real(r8), intent(in) :: frac_dst(:) -! -! !REVISION HISTORY: -! Author: Bill Sacks -! -! -! !LOCAL VARIABLES: -!EOP - real(r8) :: gdata_i ! global sum of input data - real(r8) :: gdata_o ! global sum of output data - real(r8) :: gwt_i ! global sum of input weights (area * frac) - real(r8) :: gwt_o ! global sum of output weights (area * frac) - integer :: ns_i, ns_o ! sizes of input & output grids - integer :: ni,no,k ! indices - - character(len=*), parameter :: subname = "output_diagnostics_continuous" -!------------------------------------------------------------------------------ - - ! Error check for array size consistencies - - ns_i = gridmap%na - ns_o = gridmap%nb - if (size(data_i) /= ns_i .or. & - size(data_o) /= ns_o) then - write(6,*) subname//' ERROR: array size inconsistencies for ', trim(name) - write(6,*) 'size(data_i) = ', size(data_i) - write(6,*) 'ns_i = ', ns_i - write(6,*) 'size(data_o) = ', size(data_o) - write(6,*) 'ns_o = ', ns_o - call abort() - end if - if (size(frac_dst) /= ns_o) then - write(6,*) subname//' ERROR: incorrect size of frac_dst' - write(6,*) 'size(frac_dst) = ', size(frac_dst) - write(6,*) 'ns_o = ', ns_o - call abort() - end if - if (size(mask_src) /= ns_i) then - write(6,*) subname//' ERROR: incorrect size of mask_src' - write(6,*) 'size(mask_src) = ', size(mask_src) - write(6,*) 'ns_i = ', ns_i - call abort() - end if - - ! Sums on input grid - - gdata_i = 0. - gwt_i = 0. - do ni = 1,ns_i - gdata_i = gdata_i + data_i(ni) * gridmap%area_src(ni) * mask_src(ni) - gwt_i = gwt_i + gridmap%area_src(ni) * mask_src(ni) - end do - - ! Sums on output grid - - gdata_o = 0. - gwt_o = 0. - do no = 1,ns_o - gdata_o = gdata_o + data_o(no) * gridmap%area_dst(no) * frac_dst(no) - gwt_o = gwt_o + gridmap%area_dst(no) * frac_dst(no) - end do - - ! Correct units - - gdata_i = gdata_i / gwt_i - gdata_o = gdata_o / gwt_o - - ! Diagnostic output - - write (ndiag,*) - write (ndiag,'(1x,70a1)') ('=',k=1,70) - write (ndiag,*) trim(name), ' Output' - write (ndiag,'(1x,70a1)') ('=',k=1,70) - - write (ndiag,*) - write (ndiag,'(1x,70a1)') ('.',k=1,70) - write (ndiag,2001) - write (ndiag,2002) units, units -2001 format (1x,' parameter input grid output grid') -2002 format (1x,' ', a24, a24) - write (ndiag,'(1x,70a1)') ('.',k=1,70) - write (ndiag,*) - write (ndiag,2003) name, gdata_i, gdata_o -2003 format (1x,a12, f22.3,f17.3) - -end subroutine output_diagnostics_continuous -!------------------------------------------------------------------------------ - -!------------------------------------------------------------------------------ -!BOP -! -! !IROUTINE: output_diagnostics_continuous_outonly -! -! !INTERFACE: -subroutine output_diagnostics_continuous_outonly(data_o, gridmap, name, units, ndiag) -! -! !DESCRIPTION: -! Output diagnostics for a continuous field, just on the output grid -! This is used when the average of the field on the input grid is not of interest (e.g., -! when the output quantity is the standard deviation of the input field) -! -! !USES: - use mkgridmapMod, only : gridmap_type - use mkvarpar, only : re -! -! !ARGUMENTS: - implicit none - real(r8) , intent(in) :: data_o(:) ! data on output grid - type(gridmap_type), intent(in) :: gridmap ! mapping info - character(len=*) , intent(in) :: name ! name of field - character(len=*) , intent(in) :: units ! units of field - integer , intent(in) :: ndiag ! unit number for diagnostic output -! -! !REVISION HISTORY: -! Author: Bill Sacks -! -! -! !LOCAL VARIABLES: -!EOP - real(r8) :: gdata_o ! global sum of output data - real(r8) :: gwt_o ! global sum of output weights (area * frac) - integer :: ns_o ! size of output grid - integer :: no,k ! indices - - character(len=*), parameter :: subname = "output_diagnostics_continuous_outonly" -!------------------------------------------------------------------------------ - - ! Error check for array size consistencies - - ns_o = gridmap%nb - if (size(data_o) /= ns_o) then - write(6,*) subname//' ERROR: array size inconsistencies for ', trim(name) - write(6,*) 'size(data_o) = ', size(data_o) - write(6,*) 'ns_o = ', ns_o - call abort() - end if - - ! Sums on output grid - - gdata_o = 0. - gwt_o = 0. - do no = 1,ns_o - gdata_o = gdata_o + data_o(no)*gridmap%area_dst(no)*gridmap%frac_dst(no) - gwt_o = gwt_o + gridmap%area_dst(no)*gridmap%frac_dst(no) - end do - - ! Correct units - - gdata_o = gdata_o / gwt_o - - ! Diagnostic output - - write (ndiag,*) - write (ndiag,'(1x,70a1)') ('=',k=1,70) - write (ndiag,*) trim(name), ' Output' - write (ndiag,'(1x,70a1)') ('=',k=1,70) - - write (ndiag,*) - write (ndiag,'(1x,70a1)') ('.',k=1,70) - write (ndiag,2001) - write (ndiag,2002) units -2001 format (1x,' parameter output grid') -2002 format (1x,' ', a24) - write (ndiag,'(1x,70a1)') ('.',k=1,70) - write (ndiag,*) - write (ndiag,2003) name, gdata_o -2003 format (1x,a12, f22.3) - -end subroutine output_diagnostics_continuous_outonly -!------------------------------------------------------------------------------ - -!----------------------------------------------------------------------- -subroutine output_diagnostics_index(data_i, data_o, gridmap, name, & - minval, maxval, ndiag, mask_src, frac_dst) - ! - ! !DESCRIPTION: - ! Output diagnostics for an index field: area of each index in input and output - ! - ! !USES: - use mkvarpar, only : re - use mkgridmapMod, only : gridmap_type - ! - ! !ARGUMENTS: - integer , intent(in) :: data_i(:) ! data on input grid - integer , intent(in) :: data_o(:) ! data on output grid - type(gridmap_type) , intent(in) :: gridmap ! mapping info - character(len=*) , intent(in) :: name ! name of field - integer , intent(in) :: minval ! minimum valid value - integer , intent(in) :: maxval ! minimum valid value - integer , intent(in) :: ndiag ! unit number for diagnostic output - integer , intent(in) :: mask_src(:) - real(r8) , intent(in) :: frac_dst(:) - ! - ! !LOCAL VARIABLES: - integer :: ns_i, ns_o ! sizes of input & output grids - integer :: ni, no, k ! indices - real(r8), allocatable :: garea_i(:) ! input grid: global area of each index - real(r8), allocatable :: garea_o(:) ! output grid: global area of each index - integer :: ier ! error status - - character(len=*), parameter :: subname = 'output_diagnostics_index' - !----------------------------------------------------------------------- - - ! Error check for array size consistencies - - ns_i = gridmap%na - ns_o = gridmap%nb - if (size(data_i) /= ns_i .or. & - size(data_o) /= ns_o) then - write(6,*) subname//' ERROR: array size inconsistencies for ', trim(name) - write(6,*) 'size(data_i) = ', size(data_i) - write(6,*) 'ns_i = ', ns_i - write(6,*) 'size(data_o) = ', size(data_o) - write(6,*) 'ns_o = ', ns_o - call abort() - end if - if (size(frac_dst) /= ns_o) then - write(6,*) subname//' ERROR: incorrect size of frac_dst' - write(6,*) 'size(frac_dst) = ', size(frac_dst) - write(6,*) 'ns_o = ', ns_o - call abort() - end if - if (size(mask_src) /= ns_i) then - write(6,*) subname//' ERROR: incorrect size of mask_src' - write(6,*) 'size(mask_src) = ', size(mask_src) - write(6,*) 'ns_i = ', ns_i - call abort() - end if - - ! Sum areas on input grid - - allocate(garea_i(minval:maxval), stat=ier) - if (ier/=0) call abort() - - garea_i(:) = 0. - do ni = 1, ns_i - k = data_i(ni) - if (k >= minval .and. k <= maxval) then - garea_i(k) = garea_i(k) + gridmap%area_src(ni) * mask_src(ni) * re**2 - end if - end do - - ! Sum areas on output grid - - allocate(garea_o(minval:maxval), stat=ier) - if (ier/=0) call abort() - - garea_o(:) = 0. - do no = 1, ns_o - k = data_o(no) - if (k >= minval .and. k <= maxval) then - garea_o(k) = garea_o(k) + gridmap%area_dst(no) * frac_dst(no) * re**2 - end if - end do - - ! Write results - - write (ndiag,*) - write (ndiag,'(1x,70a1)') ('=',k=1,70) - write (ndiag,*) trim(name), ' Output' - write (ndiag,'(1x,70a1)') ('=',k=1,70) - - write (ndiag,*) - write (ndiag,'(1x,70a1)') ('.',k=1,70) - write (ndiag,2001) -2001 format (1x,'index input grid area output grid area',/ & - 1x,' 10**6 km**2 10**6 km**2') - write (ndiag,'(1x,70a1)') ('.',k=1,70) - write (ndiag,*) - - do k = minval, maxval - write (ndiag,2002) k, garea_i(k)*1.e-06, garea_o(k)*1.e-06 -2002 format (1x,i9,f17.3,f18.3) - end do - - ! Deallocate memory - - deallocate(garea_i, garea_o) - -end subroutine output_diagnostics_index - - - -end module mkdiagnosticsMod diff --git a/tools/mksurfdata_map/src/mkdomainMod.F90 b/tools/mksurfdata_map/src/mkdomainMod.F90 deleted file mode 100644 index 89106f3b79..0000000000 --- a/tools/mksurfdata_map/src/mkdomainMod.F90 +++ /dev/null @@ -1,967 +0,0 @@ -module mkdomainMod -!----------------------------------------------------------------------- -!BOP -! -! !MODULE: domain1Mod -! -! !DESCRIPTION: -! Module containing 2-d global surface boundary data information -! -! !USES: - use shr_kind_mod, only : r8 => shr_kind_r8 - use mkvarpar , only : re - use nanMod , only : nan, bigint -! -! !PUBLIC TYPES: - implicit none - private -! - public :: domain_type - - type domain_type - character*16 :: set ! flag to check if domain is set - integer :: ns ! global size of domain - integer :: ni,nj ! for 2d domains only - real(r8) :: edgen ! lsmedge north - real(r8) :: edgee ! lsmedge east - real(r8) :: edges ! lsmedge south - real(r8) :: edgew ! lsmedge west - integer ,pointer :: mask(:) ! land mask: 1 = land, 0 = ocean - real(r8),pointer :: frac(:) ! fractional land - real(r8),pointer :: latc(:) ! latitude of grid cell (deg) - real(r8),pointer :: lonc(:) ! longitude of grid cell (deg) - real(r8),pointer :: lats(:) ! grid cell latitude, S edge (deg) - real(r8),pointer :: latn(:) ! grid cell latitude, N edge (deg) - real(r8),pointer :: lonw(:) ! grid cell longitude, W edge (deg) - real(r8),pointer :: lone(:) ! grid cell longitude, E edge (deg) - real(r8),pointer :: area(:) ! grid cell area (km**2) (only used for output grid) - logical :: is_2d ! if this is a 2-d domain - logical :: fracset ! if frac is set - logical :: maskset ! if mask is set - end type domain_type - -! -! !PUBLIC MEMBER FUNCTIONS: - public domain_clean - public domain_check - public domain_read - public domain_read_dims ! get dimensions from a domain file (only public for unit testing) - public domain_read_map - public domain_write - public domain_checksame - public is_domain_0to360_longs ! Does this domain have longitude on a 0 to 360 degree range - public for_test_create_domain ! For unit testing create a simple domain -! -! -! !REVISION HISTORY: -! Originally clm_varsur by Mariana Vertenstein -! Migrated from clm_varsur to domainMod by T Craig -! - character*16,parameter :: set = 'domain_set ' - character*16,parameter :: unset = 'NOdomain_unsetNO' - - real(r8) :: flandmin = 0.001 !minimum land frac for land cell -! -! !PRIVATE MEMBER FUNCTIONS: - private domain_init -! -!EOP -!------------------------------------------------------------------------------ - -contains - -!------------------------------------------------------------------------------ -!BOP -! -! !IROUTINE: domain_init -! -! !INTERFACE: - subroutine domain_init(domain,ns) -! -! !DESCRIPTION: -! This subroutine allocates and nans the domain type -! -! !ARGUMENTS: - implicit none - type(domain_type) :: domain ! domain datatype - integer :: ns ! grid size, 2d -! -! !REVISION HISTORY: -! Created by T Craig -! -! -! !LOCAL VARIABLES: -!EOP - integer ier - integer nb,ne -! -!------------------------------------------------------------------------------ - - nb = 1 - ne = ns - - if (domain%set == set) then - call domain_clean(domain) - endif - - allocate(domain%mask(ns), & - domain%frac(ns), & - domain%latc(ns), & - domain%lonc(ns), & - domain%lats(ns), & - domain%latn(ns), & - domain%lonw(ns), & - domain%lone(ns), & - domain%area(ns), stat=ier) - if (ier /= 0) then - write(6,*) 'domain_init ERROR: allocate mask, frac, lat, lon, area ' - endif - - domain%ns = ns - domain%mask = -9999 - domain%frac = -1.0e36 - domain%latc = nan - domain%lonc = nan - domain%area = nan - domain%set = set - domain%fracset = .false. - domain%maskset = .false. - - end subroutine domain_init - -!------------------------------------------------------------------------------ -!BOP -! -! !IROUTINE: domain_clean -! -! !INTERFACE: - subroutine domain_clean(domain) -! -! !DESCRIPTION: -! This subroutine deallocates the domain type -! -! !ARGUMENTS: - implicit none - type(domain_type) :: domain ! domain datatype -! -! !REVISION HISTORY: -! Created by T Craig -! -! -! !LOCAL VARIABLES: -!EOP - integer ier -! -!------------------------------------------------------------------------------ - - if (domain%set == set) then - write(6,*) 'domain_clean: cleaning ',domain%ns - deallocate(domain%mask, & - domain%frac, & - domain%latc, & - domain%lonc, & - domain%lats, & - domain%latn, & - domain%lonw, & - domain%lone, & - domain%area, stat=ier) - if (ier /= 0) then - write(6,*) 'domain_clean ERROR: deallocate mask, frac, lat, lon, area ' - call abort() - endif - else - write(6,*) 'domain_clean WARN: clean domain unecessary ' - endif - - domain%ns = bigint - domain%set = unset - domain%fracset = .false. - domain%maskset = .false. - -end subroutine domain_clean - -!------------------------------------------------------------------------------ -!BOP -! -! !IROUTINE: domain_check -! -! !INTERFACE: - subroutine domain_check(domain) -! -! !DESCRIPTION: -! This subroutine write domain info -! -! !ARGUMENTS: - implicit none - type(domain_type),intent(in) :: domain ! domain datatype -! -! !REVISION HISTORY: -! Created by T Craig -! -! -! !LOCAL VARIABLES: -! -!EOP -!------------------------------------------------------------------------------ - - write(6,*) ' domain_check set = ',trim(domain%set) - write(6,*) ' domain_check ns = ',domain%ns - write(6,*) ' domain_check lonc = ',minval(domain%lonc),maxval(domain%lonc) - write(6,*) ' domain_check latc = ',minval(domain%latc),maxval(domain%latc) - write(6,*) ' domain_check mask = ',minval(domain%mask),maxval(domain%mask) - write(6,*) ' domain_check frac = ',minval(domain%frac),maxval(domain%frac) - write(6,*) ' ' - -end subroutine domain_check - -!---------------------------------------------------------------------------- -!BOP -! -! !IROUTINE: domain_read_map -! -! !INTERFACE: - logical function domain_read_map(domain, fname) -! -! !DESCRIPTION: -! Read a grid file -! -! !USES: - use mkncdio, only : convert_latlon -! -! !ARGUMENTS: - implicit none - type(domain_type),intent(inout) :: domain - character(len=*) ,intent(in) :: fname ! this assumes a SCRIP mapping file - look at destination grid -! -! !REVISION HISTORY: -! Author: Mariana Vertenstein -! -! -! !LOCAL VARIABLES: -!EOP - include 'netcdf.inc' - integer :: i,j,n ! indices - integer :: grid_rank ! rank of domain grid - integer :: ns ! size of domain grid - integer :: ncid ! netCDF file id - integer :: dimid ! netCDF dimension id - integer :: varid ! netCDF variable id - integer :: ndims ! number of dims for variable - integer :: ier ! error status - real(r8), allocatable :: xv(:,:) ! local array for corner lons - real(r8), allocatable :: yv(:,:) ! local array for corner lats - integer :: grid_dims(2) - character(len= 32) :: subname = 'domain_read' -!----------------------------------------------------------------- - - domain_read_map = .true. - - ! Read domain file and compute stuff as needed - - call check_ret(nf_open(fname, 0, ncid), subname) - - ! Assume unstructured grid - - domain%ni = -9999 - domain%nj = -9999 - domain%is_2d = .false. - - ier = nf_inq_dimid (ncid, 'n_b', dimid) - if ( ier /= NF_NOERR )then - domain_read_map = .false. - else - call check_ret(nf_inq_dimlen (ncid, dimid, domain%ns), subname) - - call check_ret(nf_inq_dimid (ncid, 'dst_grid_rank', dimid), subname) - call check_ret(nf_inq_dimlen (ncid, dimid, grid_rank), subname) - - if (grid_rank == 2) then - call check_ret(nf_inq_varid (ncid, 'dst_grid_dims', varid), subname) - call check_ret(nf_get_var_int (ncid, varid, grid_dims), subname) - domain%ni = grid_dims(1) - domain%nj = grid_dims(2) - domain%is_2d = .true. - end if - - call domain_init(domain, domain%ns) - ns = domain%ns - - call check_ret(nf_inq_varid (ncid, 'xc_b', varid), subname) - call check_ret(nf_get_var_double (ncid, varid, domain%lonc), subname) - call convert_latlon(ncid, 'xc_b', domain%lonc) - - call check_ret(nf_inq_varid (ncid, 'yc_b', varid), subname) - call check_ret(nf_get_var_double (ncid, varid, domain%latc), subname) - call convert_latlon(ncid, 'yc_b', domain%latc) - - if (grid_rank == 2 ) then - allocate(yv(4,ns), xv(4,ns)) - call check_ret(nf_inq_varid (ncid, 'yv_b', varid), subname) - call check_ret(nf_get_var_double (ncid, varid, yv), subname) - call check_ret(nf_inq_varid (ncid, 'xv_b', varid), subname) - call check_ret(nf_get_var_double (ncid, varid, xv), subname) - - domain%lats(:) = yv(1,:) - call convert_latlon(ncid, 'yv_b', domain%lats(:)) - - domain%latn(:) = yv(3,:) - call convert_latlon(ncid, 'yv_b', domain%latn(:)) - - domain%lonw(:) = xv(1,:) - call convert_latlon(ncid, 'xv_b', domain%lonw(:)) - - domain%lone(:) = xv(2,:) - call convert_latlon(ncid, 'xv_b', domain%lone(:)) - - domain%edgen = maxval(domain%latn) - domain%edgee = maxval(domain%lone) - domain%edges = minval(domain%lats) - domain%edgew = minval(domain%lonw) - deallocate(yv,xv) - end if - - call check_ret(nf_inq_varid (ncid, 'frac_b', varid), subname) - call check_ret(nf_get_var_double (ncid, varid, domain%frac), subname) - - call check_ret(nf_inq_varid (ncid, 'area_b', varid), subname) - call check_ret(nf_get_var_double (ncid, varid, domain%area), subname) - domain%area = domain%area * re**2 - end if - domain%maskset = .true. - domain%fracset = .true. - - call check_ret(nf_close(ncid), subname) - - end function domain_read_map - -!---------------------------------------------------------------------------- -!BOP -! -! !IROUTINE: domain_read -! -! !INTERFACE: - subroutine domain_read(domain, fname, readmask) -! -! !DESCRIPTION: -! Read a grid file -! -! !USES: - use mkncdio, only : convert_latlon -! -! !ARGUMENTS: - implicit none - type(domain_type),intent(inout) :: domain - character(len=*) ,intent(in) :: fname - logical,optional, intent(in) :: readmask ! true => read mask instead of landmask for urban parameters -! -! !REVISION HISTORY: -! Author: Mariana Vertenstein -! -! -! !LOCAL VARIABLES: -!EOP - include 'netcdf.inc' - integer :: i,j,n - real(r8), allocatable :: lon1d(:) ! local array for 1d lon - real(r8), allocatable :: lat1d(:) ! local array for 1d lat - real(r8), allocatable :: xv(:,:) ! local array for corner lons - real(r8), allocatable :: yv(:,:) ! local array for corner lats - integer :: ncid ! netCDF file id - integer :: varid ! netCDF variable id - logical :: edgeNESWset ! local EDGE[NESW] - logical :: lonlatset ! local lon(:,:), lat(:,:) - logical :: llneswset ! local lat[ns],lon[we] - logical :: landfracset ! local landfrac - logical :: maskset ! local mask - integer :: ndims ! number of dims for variable - integer :: ier ! error status - logical :: lreadmask ! local readmask - character(len= 32) :: lonvar ! name of 2-d longitude variable - character(len= 32) :: latvar ! name of 2-d latitude variable - character(len= 32) :: subname = 'domain_read' -!----------------------------------------------------------------- - - lonlatset = .false. - edgeNESWset = .false. - llneswset = .false. - landfracset = .false. - maskset = .false. - lreadmask = .false. - - if (present(readmask)) then - lreadmask = readmask - end if - - call check_ret(nf_open(fname, 0, ncid), subname) - - call domain_read_dims(domain, ncid) - call domain_init(domain, domain%ns) - write(6,*) trim(subname),' initialized domain' - - ! ----- Set lat/lon variable ------ - - lonvar = ' ' - latvar = ' ' - - if (.not. lonlatset) then - ier = nf_inq_varid (ncid, 'LONGXY', varid) - if (ier == NF_NOERR) then - lonvar = 'LONGXY' - latvar = 'LATIXY' - lonlatset = .true. - end if - end if - - if (.not. lonlatset) then - ier = nf_inq_varid (ncid, 'lon', varid) - if (ier == NF_NOERR) then - lonvar = 'lon' - latvar = 'lat' - lonlatset = .true. - end if - end if - - if (.not. lonlatset) then - ier = nf_inq_varid (ncid, 'LONGITUDE', varid) - if (ier == NF_NOERR) then - lonvar = 'LONGITUDE' - latvar = 'LATITUDE' - lonlatset = .true. - end if - end if - - if (.not. lonlatset) then - write(6,*)'lon/lat values not set' - write(6,*)'currently assume either that lon/lat or LONGXY/LATIXY', & - ' or LONGITUDE/LATITUDE variables are on input dataset' - call abort() - end if - - call check_ret(nf_inq_varid (ncid, lonvar, varid), subname) - call check_ret(nf_get_var_double (ncid, varid, domain%lonc), subname) - call convert_latlon(ncid, lonvar, domain%lonc) - - call check_ret(nf_inq_varid (ncid, latvar, varid), subname) - call check_ret(nf_get_var_double (ncid, varid, domain%latc), subname) - call convert_latlon(ncid, latvar, domain%latc) - - ! ----- Set landmask/landfrac ------ - - ier = nf_inq_varid (ncid, 'frac', varid) - if (ier == NF_NOERR) then - if (landfracset) write(6,*) trim(subname),' WARNING, overwriting frac' - landfracset = .true. - write(6,*) trim(subname),' read frac' - call check_ret(nf_inq_varid (ncid, 'frac', varid), subname) - call check_ret(nf_get_var_double (ncid, varid, domain%frac), subname) - endif - - ier = nf_inq_varid (ncid, 'LANDFRAC', varid) - if (ier == NF_NOERR) then - if (landfracset) write(6,*) trim(subname),' WARNING, overwriting frac' - landfracset = .true. - write(6,*) trim(subname),' read LANDFRAC' - call check_ret(nf_inq_varid (ncid, 'LANDFRAC', varid), subname) - call check_ret(nf_get_var_double (ncid, varid, domain%frac), subname) - endif - - if (lreadmask) then - ier = nf_inq_varid (ncid, 'mask', varid) - if (ier == NF_NOERR) then - if (maskset) write(6,*) trim(subname),' WARNING, overwriting mask' - maskset = .true. - write(6,*) trim(subname),' read mask with lreadmask set' - call check_ret(nf_inq_varid (ncid, 'mask', varid), subname) - call check_ret(nf_get_var_int (ncid, varid, domain%mask), subname) - endif - else - ier = nf_inq_varid (ncid, 'mask', varid) - if (ier == NF_NOERR) then - if (maskset) write(6,*) trim(subname),' WARNING, overwriting mask' - maskset = .true. - write(6,*) trim(subname),' read mask' - call check_ret(nf_inq_varid (ncid, 'mask', varid), subname) - call check_ret(nf_get_var_int (ncid, varid, domain%mask), subname) - endif - ier = nf_inq_varid (ncid, 'LANDMASK', varid) - if (ier == NF_NOERR) then - if (maskset) write(6,*) trim(subname),' WARNING, overwriting mask' - maskset = .true. - write(6,*) trim(subname),' read LANDMASK' - call check_ret(nf_inq_varid (ncid, 'LANDMASK', varid), subname) - call check_ret(nf_get_var_int (ncid, varid, domain%mask), subname) - endif - end if - - call check_ret(nf_close(ncid), subname) - - ! ----- set derived variables ---- - - if (.not.maskset.and.landfracset) then - maskset = .true. - where (domain%frac < flandmin) - domain%mask = 0 !ocean - elsewhere - domain%mask = 1 !land - endwhere - endif - - if (.not.landfracset.and.maskset) then - landfracset = .true. - do n = 1,domain%ns - if ( domain%mask(n) == 0 )then - domain%frac(n) = 0._r8 !ocean - else - domain%frac(n) = 1._r8 !land - end if - end do - endif - domain%maskset = maskset - domain%fracset = landfracset - - end subroutine domain_read - -!---------------------------------------------------------------------------- -!BOP -! -! !IROUTINE: domain_read_dims -! -! !INTERFACE: - subroutine domain_read_dims(domain, ncid) -! -! !DESCRIPTION: -! get dimension size(s) from a domain file -! sets domain%ns, domain%is_2d; and (if 2-d) domain%ni and domain%nj -! -! !ARGUMENTS: - implicit none - type(domain_type),intent(inout) :: domain - integer ,intent(in) :: ncid ! ID of an open netcdf file -! -! !REVISION HISTORY: -! Author: Bill Sacks -! -! -! !LOCAL VARIABLES: -!EOP - logical :: dimset ! has dimension information been set? - character(len= 32) :: subname = 'domain_read_dims' -!----------------------------------------------------------------- - - ! Assume unstructured grid - domain%ni = -9999 - domain%nj = -9999 - domain%is_2d = .false. - - dimset = .false. - - ! Note: We use the first dimension that is found in the following list - - ! ----- First try to find 2-d info ------ - - call domain_read_dims_2d(domain, dimset, ncid, 'lsmlon', 'lsmlat') - call domain_read_dims_2d(domain, dimset, ncid, 'ni', 'nj') - call domain_read_dims_2d(domain, dimset, ncid, 'lon', 'lat') - - ! ----- If we haven't found 2-d info, try to find 1-d info ----- - - call domain_read_dims_1d(domain, dimset, ncid, 'num_pixels') - - ! ----- If we haven't found any info, abort ----- - - if (.not. dimset) then - write(6,*) trim(subname),' ERROR: dims not set' - call abort() - endif - - contains - -!---------------------------------------------------------------------------- -!BOP -! -! !IROUTINE: domain_read_dims_2d -! -! !INTERFACE: - subroutine domain_read_dims_2d(domain, dimset, ncid, lon_name, lat_name) -! -! !DESCRIPTION: -! Try to read 2-d dimension size information -! -! Checks whether the given lon_name is found in the netcdf file. If it is: -! (a) If dimset is already true, then it issues a warning and returns -! (b) If dimset is false, then this sets: -! - domain%ni -! - domain%nj -! - domain%ns -! - domain%is_2d -! - dimset = true -! -! If the given lon_name is not found, the above variables are left unchanged -! -! !ARGUMENTS: - implicit none - type(domain_type),intent(inout) :: domain - logical ,intent(inout) :: dimset ! has dimension information been set? - integer ,intent(in) :: ncid ! ID of an open netCDF file - character(len=*) ,intent(in) :: lon_name - character(len=*) ,intent(in) :: lat_name -! -! !REVISION HISTORY: -! Author: Bill Sacks -! -! -! !LOCAL VARIABLES: -!EOP - include 'netcdf.inc' - integer :: dimid ! netCDF dimension id - integer :: nlon,nlat ! size - integer :: ier ! error status - - character(len= 32) :: subname = 'domain_read_dims_2d' - -!----------------------------------------------------------------- - - ier = nf_inq_dimid (ncid, lon_name, dimid) - if (ier == NF_NOERR) then - if (dimset) then - write(6,*) trim(subname),' WARNING: dimension sizes already set; skipping ', & - lon_name, '/', lat_name - else - write(6,*) trim(subname),' read lon and lat dims from ', lon_name, '/', lat_name - call check_ret(nf_inq_dimid (ncid, lon_name, dimid), subname) - call check_ret(nf_inq_dimlen (ncid, dimid, nlon), subname) - call check_ret(nf_inq_dimid (ncid, lat_name, dimid), subname) - call check_ret(nf_inq_dimlen (ncid, dimid, nlat), subname) - domain%ni = nlon - domain%nj = nlat - domain%ns = nlon * nlat - domain%is_2d = .true. - dimset = .true. - end if - endif - - end subroutine domain_read_dims_2d - - -!---------------------------------------------------------------------------- -!BOP -! -! !IROUTINE: domain_read_dims_1d -! -! !INTERFACE: - subroutine domain_read_dims_1d(domain, dimset, ncid, dim_name) -! -! !DESCRIPTION: -! Try to read 1-d dimension size information -! -! Checks whether the given dim_name is found in the netcdf file. If it is: -! (a) If dimset is already true, then it issues a warning and returns -! (b) If dimset is false, then this sets: -! - domain%ns -! - domain%is_2d -! - dimset = true -! -! If the given dim_name is not found, the above variables are left unchanged -! -! !ARGUMENTS: - implicit none - type(domain_type),intent(inout) :: domain - logical ,intent(inout) :: dimset ! has dimension information been set? - integer ,intent(in) :: ncid ! ID of an open netCDF file - character(len=*) ,intent(in) :: dim_name -! -! !REVISION HISTORY: -! Author: Bill Sacks -! -! -! !LOCAL VARIABLES: -!EOP - include 'netcdf.inc' - integer :: dimid ! netCDF dimension id - integer :: npts ! size - integer :: ier ! error status - - character(len= 32) :: subname = 'domain_read_dims_1d' - -!----------------------------------------------------------------- - - ier = nf_inq_dimid (ncid, dim_name, dimid) - if (ier == NF_NOERR) then - if (dimset) then - write(6,*) trim(subname),' WARNING: dimension sizes already set; skipping ', dim_name - else - write(6,*) trim(subname),' read 1-d length from ', dim_name - call check_ret(nf_inq_dimid (ncid, dim_name, dimid), subname) - call check_ret(nf_inq_dimlen (ncid, dimid, npts), subname) - domain%ns = npts - domain%is_2d = .false. - dimset = .true. - end if - endif - - end subroutine domain_read_dims_1d - - end subroutine domain_read_dims - - -!---------------------------------------------------------------------------- -!BOP -! -! !IROUTINE: domain_write -! -! !INTERFACE: - subroutine domain_write(domain,fname) -! -! !DESCRIPTION: -! Write a domain to netcdf - -! !ARGUMENTS: - implicit none - include 'netcdf.inc' - type(domain_type),intent(inout) :: domain - character(len=*) ,intent(in) :: fname -! -! !REVISION HISTORY: -! Author: T Craig -! -! -! !LOCAL VARIABLES: -!EOP - integer :: varid !netCDF variable id - integer :: ncid !netCDF file id - integer :: omode !netCDF output mode - character(len= 32) :: subname = 'domain_write' -!----------------------------------------------------------------- - - call check_ret(nf_open(trim(fname), nf_write, ncid), subname) - ! File will be in define mode. Set fill mode to "no fill" to optimize performance - - call check_ret(nf_set_fill (ncid, nf_nofill, omode), subname) - - ! Write domain fields - - call check_ret(nf_inq_varid(ncid, 'AREA', varid), subname) - call check_ret(nf_put_var_double(ncid, varid, domain%area), subname) - - call check_ret(nf_inq_varid(ncid, 'LONGXY', varid), subname) - call check_ret(nf_put_var_double(ncid, varid, domain%lonc), subname) - - call check_ret(nf_inq_varid(ncid, 'LATIXY', varid), subname) - call check_ret(nf_put_var_double(ncid, varid, domain%latc), subname) - - ! Synchronize the disk copy of a netCDF dataset with in-memory buffers - - call check_ret(nf_sync(ncid), subname) - - ! Close grid data dataset - - call check_ret(nf_close(ncid), subname) - - end subroutine domain_write - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: check_ret -! -! !INTERFACE: - subroutine check_ret(ret, calling) -! -! !DESCRIPTION: -! Check return status from netcdf call -! -! !ARGUMENTS: - implicit none - include 'netcdf.inc' - integer, intent(in) :: ret - character(len=*) :: calling -! -! !REVISION HISTORY: -! -!EOP -!----------------------------------------------------------------------- - - if (ret /= NF_NOERR) then - write(6,*)'netcdf error from ',trim(calling), ' rcode = ', ret, & - ' error = ', NF_STRERROR(ret) - call abort() - end if - - end subroutine check_ret - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: domain_checksame -! -! !INTERFACE: - subroutine domain_checksame( srcdomain, dstdomain, tgridmap ) -! -! !DESCRIPTION: -! Check that the input domains agree with the input map -! -! USES: - use mkgridmapMod, only : gridmap_type, gridmap_setptrs -! !ARGUMENTS: - implicit none - type(domain_type), intent(in) :: srcdomain ! input domain - type(domain_type), intent(in) :: dstdomain ! output domain - type(gridmap_type),intent(in) :: tgridmap ! grid map -! -! !REVISION HISTORY: -! -!EOP -!----------------------------------------------------------------------- - integer :: na, nb, ns ! gridmap sizes - integer :: n, ni ! indices - real(r8), pointer :: xc_src(:) ! Source longitude - real(r8), pointer :: yc_src(:) ! Source latitude - integer, pointer :: src_indx(:) ! Source index - real(r8), pointer :: xc_dst(:) ! Destination longitude - real(r8), pointer :: yc_dst(:) ! Destination latitude - integer, pointer :: dst_indx(:) ! Destination index - character(len= 32) :: subname = 'domain_checksame' - - ! tolerance for checking equality of lat & lon - ! We allow for single-precision rounding-level differences (approx. 1.2e-7 relative - ! error) For a value of 360 (max value for lat / lon), this means we can allow - ! absolute errors of about 5e-5. - real(r8), parameter :: eps = 5.e-5_r8 - - - if (srcdomain%set == unset) then - write(6,*) trim(subname)//'ERROR: source domain is unset!' - call abort() - end if - if (dstdomain%set == unset) then - write(6,*) trim(subname)//'ERROR: destination domain is unset!' - call abort() - end if - - call gridmap_setptrs( tgridmap, nsrc=na, ndst=nb, ns=ns, & - xc_src=xc_src, yc_src=yc_src, & - xc_dst=xc_dst, yc_dst=yc_dst, & - src_indx=src_indx, dst_indx=dst_indx & - ) - - if (srcdomain%ns /= na) then - write(6,*) trim(subname)// & - ' ERROR: input domain size and gridmap source size are not the same size' - write(6,*)' domain size = ',srcdomain%ns - write(6,*)' map src size= ',na - call abort() - end if - if (dstdomain%ns /= nb) then - write(6,*) trim(subname)// & - ' ERROR: output domain size and gridmap destination size are not the same size' - write(6,*)' domain size = ',dstdomain%ns - write(6,*)' map dst size= ',nb - call abort() - end if - do n = 1,ns - ni = src_indx(n) - if (abs(srcdomain%lonc(ni) - xc_src(ni)) > eps) then - write(6,*) trim(subname)// & - ' ERROR: input domain lon and gridmap lon not the same at ni = ',ni - write(6,*)' domain lon= ',srcdomain%lonc(ni) - write(6,*)' gridmap lon= ',xc_src(ni) - call abort() - end if - if (abs(srcdomain%latc(ni) - yc_src(ni)) > eps) then - write(6,*) trim(subname)// & - ' ERROR: input domain lat and gridmap lat not the same at ni = ',ni - write(6,*)' domain lat= ',srcdomain%latc(ni) - write(6,*)' gridmap lat= ',yc_src(ni) - call abort() - end if - end do - do n = 1,ns - ni = dst_indx(n) - if (abs(dstdomain%lonc(ni) - xc_dst(ni)) > eps) then - write(6,*) trim(subname)// & - ' ERROR: output domain lon and gridmap lon not the same at ni = ',ni - write(6,*)' domain lon= ',dstdomain%lonc(ni) - write(6,*)' gridmap lon= ',xc_dst(ni) - call abort() - end if - if (abs(dstdomain%latc(ni) - yc_dst(ni)) > eps) then - write(6,*) trim(subname)// & - ' ERROR: output domain lat and gridmap lat not the same at ni = ',ni - write(6,*)' domain lat= ',dstdomain%latc(ni) - write(6,*)' gridmap lat= ',yc_dst(ni) - call abort() - end if - end do - end subroutine domain_checksame - - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: is_domain_0to360_longs -! -! !INTERFACE: - logical function is_domain_0to360_longs( domain ) -! -! !DESCRIPTION: -! Check if the domain has longitudes on a -180 to 180 grid or a 0 to 360 grid. -! CESM requires the later right now. -! -! USES: - use mkgridmapMod, only : gridmap_type, gridmap_setptrs -! !ARGUMENTS: - implicit none - type(domain_type), intent(in) :: domain ! input domain -! -! !REVISION HISTORY: -! -!EOP -!----------------------------------------------------------------------- - if ( any(domain%lonc < 0.0_r8) )then - is_domain_0to360_longs = .false. - else - is_domain_0to360_longs = .true. - end if - end function is_domain_0to360_longs - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: for_test_create_domain -! -! !INTERFACE: - subroutine for_test_create_domain( domain ) -! -! !DESCRIPTION: -! Create a simple domain for unit testing -! -! USES: - implicit none -! !ARGUMENTS: - type(domain_type), intent(inout) :: domain ! input domain -! !LOCAL VARIABLES: - integer, parameter :: ns_o = 2 - - call domain_init( domain, ns_o ) - domain%latc = (/ 42.0_r8, 40.0_r8 /) - domain%lonc = (/ -105.0_r8, -100.0_r8 /) - domain%latn = (/ 43.0_r8, 41.0_r8 /) - domain%lats = (/ 41.0_r8, 39.0_r8 /) - domain%lone = (/ -104.0_r8, -99.0_r8 /) - domain%lonw = (/ -106.0_r8, -101.0_r8 /) - domain%mask = (/ 1, 1 /) - domain%frac = (/ 1.0_r8, 1.0_r8 /) - domain%area = (/ 49284.0_r8, 49284.0_r8 /) ! This is NOT the correct area! - - domain%edgen = maxval( domain%latn ) - domain%edges = minval( domain%lats ) - domain%edgew = minval( domain%lonw ) - domain%edgee = maxval( domain%lone ) - - domain%maskset = .true. - domain%fracset = .true. - domain%is_2d = .false. - - end subroutine for_test_create_domain - -end module mkdomainMod diff --git a/tools/mksurfdata_map/src/mkfileMod.F90 b/tools/mksurfdata_map/src/mkfileMod.F90 deleted file mode 100644 index 43bdda4c12..0000000000 --- a/tools/mksurfdata_map/src/mkfileMod.F90 +++ /dev/null @@ -1,566 +0,0 @@ -module mkfileMod - -contains - -!----------------------------------------------------------------------- - subroutine mkfile(domain, fname, harvdata, dynlanduse) - - use shr_kind_mod , only : r8 => shr_kind_r8 - use shr_sys_mod , only : shr_sys_getenv - use fileutils , only : get_filename - use mkvarpar , only : nlevsoi, numrad, numstdpft - use mkvarctl - use mkurbanparMod, only : numurbl, nlevurb - use mkglcmecMod , only : nglcec - use mkpftMod , only : mkpftAtt - use mksoilMod , only : mksoilAtt - use mkharvestMod , only : mkharvest_fieldname, mkharvest_numtypes, mkharvest_longname - use mkharvestMod , only : mkharvest_units, harvestDataType - use mkncdio , only : check_ret, ncd_defvar, ncd_def_spatial_var - use mkdomainMod - - implicit none - include 'netcdf.inc' - type(domain_type) , intent(in) :: domain - character(len=*) , intent(in) :: fname - logical , intent(in) :: dynlanduse - type(harvestDataType), intent(in) :: harvdata - - integer :: ncid - integer :: j ! index - integer :: dimid ! temporary - integer :: values(8) ! temporary - character(len=256) :: str ! global attribute string - character(len=256) :: name ! name of attribute - character(len=256) :: unit ! units of attribute - character(len= 18) :: datetime ! temporary - character(len= 8) :: date ! temporary - character(len= 10) :: time ! temporary - character(len= 5) :: zone ! temporary - integer :: ier ! error status - integer :: omode ! netCDF output mode - integer :: xtype ! external type - integer, allocatable :: ind1D(:)! Indices of 1D harvest variables - integer, allocatable :: ind2D(:)! Indices of 2D harvest variables - character(len=32) :: subname = 'mkfile' ! subroutine name -!----------------------------------------------------------------------- - - call check_ret(nf_create(trim(fname), ior(nf_clobber,nf_64bit_offset), & - ncid), subname) - - call check_ret(nf_set_fill (ncid, nf_nofill, omode), subname) - - ! Define dimensions. - - if (outnc_1d) then - call check_ret(nf_def_dim (ncid, 'gridcell', domain%ns, dimid), subname) - else - call check_ret(nf_def_dim (ncid, 'lsmlon' , domain%ni, dimid), subname) - call check_ret(nf_def_dim (ncid, 'lsmlat' , domain%nj, dimid), subname) - end if - - if (.not. dynlanduse) then - call check_ret(nf_def_dim (ncid, 'nglcec' , nglcec , dimid), subname) - call check_ret(nf_def_dim (ncid, 'nglcecp1', nglcec+1 , dimid), subname) - end if - call check_ret(nf_def_dim (ncid, 'numurbl' , numurbl , dimid), subname) - call check_ret(nf_def_dim (ncid, 'nlevurb' , nlevurb , dimid), subname) - call check_ret(nf_def_dim (ncid, 'numrad' , numrad , dimid), subname) - call check_ret(nf_def_dim (ncid, 'nchar' , 256 , dimid), subname) - - ! Create global attributes. - - str = 'NCAR-CSM' - call check_ret(nf_put_att_text (ncid, NF_GLOBAL, & - 'Conventions', len_trim(str), trim(str)), subname) - - call date_and_time (date, time, zone, values) - datetime(1:8) = date(5:6) // '-' // date(7:8) // '-' // date(3:4) - datetime(9:) = ' ' // time(1:2) // ':' // time(3:4) // ':' // time(5:6) // ' ' - str = 'created on: ' // datetime - call check_ret(nf_put_att_text (ncid, NF_GLOBAL, & - 'History_Log', len_trim(str), trim(str)), subname) - - call shr_sys_getenv ('LOGNAME', str, ier) - call check_ret(nf_put_att_text (ncid, NF_GLOBAL, & - 'Logname', len_trim(str), trim(str)), subname) - - call shr_sys_getenv ('HOST', str, ier) - call check_ret(nf_put_att_text (ncid, NF_GLOBAL, & - 'Host', len_trim(str), trim(str)), subname) - - str = 'Community Land Model: CLM5' - call check_ret(nf_put_att_text (ncid, NF_GLOBAL, & - 'Source', len_trim(str), trim(str)), subname) - - call check_ret(nf_put_att_text (ncid, NF_GLOBAL, & - 'Version', len_trim(gitdescribe), trim(gitdescribe)), subname) - -#ifdef OPT - str = 'TRUE' -#else - str = 'FALSE' -#endif - - call check_ret(nf_put_att_text (ncid, NF_GLOBAL, & - 'Compiler_Optimized', len_trim(str), trim(str)), subname) - - if ( all_urban )then - str = 'TRUE' - call check_ret(nf_put_att_text(ncid, NF_GLOBAL, & - 'all_urban', len_trim(str), trim(str)), subname) - end if - - if ( no_inlandwet )then - str = 'TRUE' - call check_ret(nf_put_att_text(ncid, NF_GLOBAL, & - 'no_inlandwet', len_trim(str), trim(str)), subname) - end if - - call check_ret(nf_put_att_int(ncid, NF_GLOBAL, & - 'nglcec', nf_int, 1, nglcec), subname) - - ! Raw data file names - - str = get_filename(mksrf_fgrid) - call check_ret(nf_put_att_text(ncid, NF_GLOBAL, & - 'Input_grid_dataset', len_trim(str), trim(str)), subname) - - str = trim(mksrf_gridtype) - call check_ret(nf_put_att_text(ncid, NF_GLOBAL, & - 'Input_gridtype', len_trim(str), trim(str)), subname) - - if (.not. dynlanduse) then - str = get_filename(mksrf_fvocef) - call check_ret(nf_put_att_text(ncid, NF_GLOBAL, & - 'VOC_EF_raw_data_file_name', len_trim(str), trim(str)), subname) - end if - - str = get_filename(mksrf_flakwat) - call check_ret(nf_put_att_text(ncid, NF_GLOBAL, & - 'Inland_lake_raw_data_file_name', len_trim(str), trim(str)), subname) - - str = get_filename(mksrf_fwetlnd) - call check_ret(nf_put_att_text(ncid, NF_GLOBAL, & - 'Inland_wetland_raw_data_file_name', len_trim(str), trim(str)), subname) - - str = get_filename(mksrf_fglacier) - call check_ret(nf_put_att_text(ncid, NF_GLOBAL, & - 'Glacier_raw_data_file_name', len_trim(str), trim(str)), subname) - - str = get_filename(mksrf_fglacierregion) - call check_ret(nf_put_att_text(ncid, NF_GLOBAL, & - 'Glacier_region_raw_data_file_name', len_trim(str), trim(str)), subname) - - str = get_filename(mksrf_furbtopo) - call check_ret(nf_put_att_text(ncid, NF_GLOBAL, & - 'Urban_Topography_raw_data_file_name', len_trim(str), trim(str)), subname) - - str = get_filename(mksrf_furban) - call check_ret(nf_put_att_text(ncid, NF_GLOBAL, & - 'Urban_raw_data_file_name', len_trim(str), trim(str)), subname) - - if (.not. dynlanduse .and. (numpft == numstdpft) ) then - str = get_filename(mksrf_flai) - call check_ret(nf_put_att_text(ncid, NF_GLOBAL, & - 'Lai_raw_data_file_name', len_trim(str), trim(str)), subname) - end if - - str = get_filename(mksrf_fabm) - call check_ret(nf_put_att_text(ncid, NF_GLOBAL, & - 'agfirepkmon_raw_data_file_name', len_trim(str), trim(str)), subname) - - str = get_filename(mksrf_fgdp) - call check_ret(nf_put_att_text(ncid, NF_GLOBAL, & - 'gdp_raw_data_file_name', len_trim(str), trim(str)), subname) - - str = get_filename(mksrf_fpeat) - call check_ret(nf_put_att_text(ncid, NF_GLOBAL, & - 'peatland_raw_data_file_name', len_trim(str), trim(str)), subname) - - str = get_filename(mksrf_fsoildepth) - call check_ret(nf_put_att_text(ncid, NF_GLOBAL, & - 'soildepth_raw_data_file_name', len_trim(str), trim(str)), subname) - - str = get_filename(mksrf_ftopostats) - call check_ret(nf_put_att_text(ncid, NF_GLOBAL, & - 'topography_stats_raw_data_file_name', len_trim(str), trim(str)), subname) - - if ( outnc_vic )then - str = get_filename(mksrf_fvic) - call check_ret(nf_put_att_text(ncid, NF_GLOBAL, & - 'vic_raw_data_file_name', len_trim(str), trim(str)), subname) - end if - - ! Mapping file names - - str = get_filename(map_fpft) - call check_ret(nf_put_att_text(ncid, NF_GLOBAL, & - 'map_pft_file_name', len_trim(str), trim(str)), subname) - - str = get_filename(map_flakwat) - call check_ret(nf_put_att_text(ncid, NF_GLOBAL, & - 'map_lakwat_file', len_trim(str), trim(str)), subname) - - str = get_filename(map_fwetlnd) - call check_ret(nf_put_att_text(ncid, NF_GLOBAL, & - 'map_wetlnd_file', len_trim(str), trim(str)), subname) - - str = get_filename(map_fglacier) - call check_ret(nf_put_att_text(ncid, NF_GLOBAL, & - 'map_glacier_file', len_trim(str), trim(str)), subname) - - str = get_filename(map_fglacierregion) - call check_ret(nf_put_att_text(ncid, NF_GLOBAL, & - 'map_glacier_region_file', len_trim(str), trim(str)), subname) - - str = get_filename(map_fsoitex) - call check_ret(nf_put_att_text(ncid, NF_GLOBAL, & - 'map_soil_texture_file', len_trim(str), trim(str)), subname) - - str = get_filename(map_fsoicol) - call check_ret(nf_put_att_text(ncid, NF_GLOBAL, & - 'map_soil_color_file', len_trim(str), trim(str)), subname) - - str = get_filename(map_forganic) - call check_ret(nf_put_att_text(ncid, NF_GLOBAL, & - 'map_soil_organic_file', len_trim(str), trim(str)), subname) - - str = get_filename(map_furban) - call check_ret(nf_put_att_text(ncid, NF_GLOBAL, & - 'map_urban_file', len_trim(str), trim(str)), subname) - - str = get_filename(map_fmax) - call check_ret(nf_put_att_text(ncid, NF_GLOBAL, & - 'map_fmax_file', len_trim(str), trim(str)), subname) - - str = get_filename(map_fvocef) - call check_ret(nf_put_att_text(ncid, NF_GLOBAL, & - 'map_VOC_EF_file', len_trim(str), trim(str)), subname) - - str = get_filename(map_fharvest) - call check_ret(nf_put_att_text(ncid, NF_GLOBAL, & - 'map_harvest_file', len_trim(str), trim(str)), subname) - - if ( numpft == numstdpft )then - str = get_filename(map_flai) - call check_ret(nf_put_att_text(ncid, NF_GLOBAL, & - 'map_lai_sai_file', len_trim(str), trim(str)), subname) - end if - - str = get_filename(map_furbtopo) - call check_ret(nf_put_att_text(ncid, NF_GLOBAL, & - 'map_urban_topography_file', len_trim(str), trim(str)), subname) - - str = get_filename(map_fabm) - call check_ret(nf_put_att_text(ncid, NF_GLOBAL, & - 'map_agfirepkmon_file', len_trim(str), trim(str)), subname) - - str = get_filename(map_fgdp) - call check_ret(nf_put_att_text(ncid, NF_GLOBAL, & - 'map_gdp_file', len_trim(str), trim(str)), subname) - - str = get_filename(map_fpeat) - call check_ret(nf_put_att_text(ncid, NF_GLOBAL, & - 'map_peatland_file', len_trim(str), trim(str)), subname) - - str = get_filename(map_fsoildepth) - call check_ret(nf_put_att_text(ncid, NF_GLOBAL, & - 'map_soildepth_file', len_trim(str), trim(str)), subname) - - str = get_filename(map_ftopostats) - call check_ret(nf_put_att_text(ncid, NF_GLOBAL, & - 'map_topography_stats_file', len_trim(str), trim(str)), subname) - - if ( outnc_vic )then - str = get_filename(map_fvic) - call check_ret(nf_put_att_text(ncid, NF_GLOBAL, & - 'map_vic_file', len_trim(str), trim(str)), subname) - end if - - ! ---------------------------------------------------------------------- - ! Define variables - ! ---------------------------------------------------------------------- - - if ( .not. outnc_double )then - xtype = nf_float - else - xtype = nf_double - end if - - call mksoilAtt( ncid, dynlanduse, xtype ) - - call mkpftAtt( ncid, dynlanduse, xtype ) - - call ncd_def_spatial_var(ncid=ncid, varname='AREA' , xtype=nf_double, & - long_name='area', units='km^2') - - call ncd_def_spatial_var(ncid=ncid, varname='LONGXY', xtype=nf_double, & - long_name='longitude', units='degrees east') - - call ncd_def_spatial_var(ncid=ncid, varname='LATIXY', xtype=nf_double, & - long_name='latitude', units='degrees north') - - if (.not. dynlanduse) then - call ncd_def_spatial_var(ncid=ncid, varname='EF1_BTR', xtype=xtype, & - long_name='EF btr (isoprene)', units='unitless') - - call ncd_def_spatial_var(ncid=ncid, varname='EF1_FET', xtype=xtype, & - long_name='EF fet (isoprene)', units='unitless') - - call ncd_def_spatial_var(ncid=ncid, varname='EF1_FDT', xtype=xtype, & - long_name='EF fdt (isoprene)', units='unitless') - - call ncd_def_spatial_var(ncid=ncid, varname='EF1_SHR', xtype=xtype, & - long_name='EF shr (isoprene)', units='unitless') - - call ncd_def_spatial_var(ncid=ncid, varname='EF1_GRS', xtype=xtype, & - long_name='EF grs (isoprene)', units='unitless') - - call ncd_def_spatial_var(ncid=ncid, varname='EF1_CRP', xtype=xtype, & - long_name='EF crp (isoprene)', units='unitless') - - call ncd_def_spatial_var(ncid=ncid, varname='CANYON_HWR', xtype=xtype, & - lev1name='numurbl', & - long_name='canyon height to width ratio', units='unitless') - - call ncd_def_spatial_var(ncid=ncid, varname='EM_IMPROAD', xtype=xtype, & - lev1name='numurbl', & - long_name='emissivity of impervious road', units='unitless') - - call ncd_def_spatial_var(ncid=ncid, varname='EM_PERROAD', xtype=xtype, & - lev1name='numurbl', & - long_name='emissivity of pervious road', units='unitless') - - call ncd_def_spatial_var(ncid=ncid, varname='EM_ROOF', xtype=xtype, & - lev1name='numurbl', & - long_name='emissivity of roof', units='unitless') - - call ncd_def_spatial_var(ncid=ncid, varname='EM_WALL', xtype=xtype, & - lev1name='numurbl', & - long_name='emissivity of wall', units='unitless') - - call ncd_def_spatial_var(ncid=ncid, varname='HT_ROOF', xtype=xtype, & - lev1name='numurbl', & - long_name='height of roof', units='meters') - - call ncd_def_spatial_var(ncid=ncid, varname='THICK_ROOF', xtype=xtype, & - lev1name='numurbl', & - long_name='thickness of roof', units='meters') - - call ncd_def_spatial_var(ncid=ncid, varname='THICK_WALL', xtype=xtype, & - lev1name='numurbl', & - long_name='thickness of wall', units='meters') - - call ncd_def_spatial_var(ncid=ncid, varname='T_BUILDING_MIN', xtype=xtype, & - lev1name='numurbl', & - long_name='minimum interior building temperature', units='K') - - call ncd_def_spatial_var(ncid=ncid, varname='WIND_HGT_CANYON', xtype=xtype, & - lev1name='numurbl', & - long_name='height of wind in canyon', units='meters') - - call ncd_def_spatial_var(ncid=ncid, varname='WTLUNIT_ROOF', xtype=xtype, & - lev1name='numurbl', & - long_name='fraction of roof', units='unitless') - - call ncd_def_spatial_var(ncid=ncid, varname='WTROAD_PERV', xtype=xtype, & - lev1name='numurbl', & - long_name='fraction of pervious road', units='unitless') - - call ncd_def_spatial_var(ncid=ncid, varname='ALB_IMPROAD_DIR', xtype=xtype, & - lev1name='numurbl', lev2name='numrad', & - long_name='direct albedo of impervious road', units='unitless') - - call ncd_def_spatial_var(ncid=ncid, varname='ALB_IMPROAD_DIF', xtype=xtype, & - lev1name='numurbl', lev2name='numrad', & - long_name='diffuse albedo of impervious road', units='unitless') - - call ncd_def_spatial_var(ncid=ncid, varname='ALB_PERROAD_DIR', xtype=xtype, & - lev1name='numurbl', lev2name='numrad', & - long_name='direct albedo of pervious road', units='unitless') - - call ncd_def_spatial_var(ncid=ncid, varname='ALB_PERROAD_DIF', xtype=xtype, & - lev1name='numurbl', lev2name='numrad', & - long_name='diffuse albedo of pervious road', units='unitless') - - call ncd_def_spatial_var(ncid=ncid, varname='ALB_ROOF_DIR', xtype=xtype, & - lev1name='numurbl', lev2name='numrad', & - long_name='direct albedo of roof', units='unitless') - - call ncd_def_spatial_var(ncid=ncid, varname='ALB_ROOF_DIF', xtype=xtype, & - lev1name='numurbl', lev2name='numrad', & - long_name='diffuse albedo of roof', units='unitless') - - call ncd_def_spatial_var(ncid=ncid, varname='ALB_WALL_DIR', xtype=xtype, & - lev1name='numurbl', lev2name='numrad', & - long_name='direct albedo of wall', units='unitless') - - call ncd_def_spatial_var(ncid=ncid, varname='ALB_WALL_DIF', xtype=xtype, & - lev1name='numurbl', lev2name='numrad', & - long_name='diffuse albedo of wall', units='unitless') - - call ncd_def_spatial_var(ncid=ncid, varname='TK_ROOF', xtype=xtype, & - lev1name='numurbl', lev2name='nlevurb', & - long_name='thermal conductivity of roof', units='W/m*K') - - call ncd_def_spatial_var(ncid=ncid, varname='TK_WALL', xtype=xtype, & - lev1name='numurbl', lev2name='nlevurb', & - long_name='thermal conductivity of wall', units='W/m*K') - - call ncd_def_spatial_var(ncid=ncid, varname='TK_IMPROAD', xtype=xtype, & - lev1name='numurbl', lev2name='nlevurb', & - long_name='thermal conductivity of impervious road', units='W/m*K') - - call ncd_def_spatial_var(ncid=ncid, varname='CV_ROOF', xtype=xtype, & - lev1name='numurbl', lev2name='nlevurb', & - long_name='volumetric heat capacity of roof', units='J/m^3*K') - - call ncd_def_spatial_var(ncid=ncid, varname='CV_WALL', xtype=xtype, & - lev1name='numurbl', lev2name='nlevurb', & - long_name='volumetric heat capacity of wall', units='J/m^3*K') - - call ncd_def_spatial_var(ncid=ncid, varname='CV_IMPROAD', xtype=xtype, & - lev1name='numurbl', lev2name='nlevurb', & - long_name='volumetric heat capacity of impervious road', units='J/m^3*K') - - call ncd_def_spatial_var(ncid=ncid, varname='NLEV_IMPROAD', xtype=nf_int, & - lev1name='numurbl', & - long_name='number of impervious road layers', units='unitless') - - call ncd_def_spatial_var(ncid=ncid, varname='peatf', xtype=xtype, & - long_name='peatland fraction', units='unitless') - - call ncd_def_spatial_var(ncid=ncid, varname='zbedrock', xtype=xtype, & - long_name='soil depth', units='m') - - call ncd_def_spatial_var(ncid=ncid, varname='abm', xtype=nf_int, & - long_name='agricultural fire peak month', units='unitless') - - call ncd_def_spatial_var(ncid=ncid, varname='gdp', xtype=xtype, & - long_name='gdp', units='unitless') - - call ncd_def_spatial_var(ncid=ncid, varname='SLOPE', xtype=xtype, & - long_name='mean topographic slope', units='degrees') - - call ncd_def_spatial_var(ncid=ncid, varname='STD_ELEV', xtype=xtype, & - long_name='standard deviation of elevation', units='m') - - if ( outnc_vic )then - call ncd_def_spatial_var(ncid=ncid, varname='binfl', xtype=xtype, & - long_name='VIC b parameter for the Variable Infiltration Capacity Curve', units='unitless') - - call ncd_def_spatial_var(ncid=ncid, varname='Ws', xtype=xtype, & - long_name='VIC Ws parameter for the ARNO curve', units='unitless') - - call ncd_def_spatial_var(ncid=ncid, varname='Dsmax', xtype=xtype, & - long_name='VIC Dsmax parameter for the ARNO curve', units='mm/day') - - call ncd_def_spatial_var(ncid=ncid, varname='Ds', xtype=xtype, & - long_name='VIC Ds parameter for the ARNO curve', units='unitless') - - end if - call ncd_def_spatial_var(ncid=ncid, varname='LAKEDEPTH', xtype=xtype, & - long_name='lake depth', units='m') - - call ncd_def_spatial_var(ncid=ncid, varname='PCT_WETLAND', xtype=xtype, & - long_name='percent wetland', units='unitless') - - call ncd_def_spatial_var(ncid=ncid, varname='PCT_LAKE', xtype=xtype, & - long_name='percent lake', units='unitless') - - call ncd_def_spatial_var(ncid=ncid, varname='PCT_GLACIER', xtype=xtype, & - long_name='percent glacier', units='unitless') - - call ncd_def_spatial_var(ncid=ncid, varname='GLACIER_REGION', xtype=nf_int, & - long_name='glacier region ID', units='unitless') - - call ncd_defvar(ncid=ncid, varname='GLC_MEC', xtype=xtype, & - dim1name='nglcecp1', long_name='Glacier elevation class', units='m') - - call ncd_def_spatial_var(ncid=ncid, varname='PCT_GLC_MEC', xtype=xtype, & - lev1name='nglcec', & - long_name='percent glacier for each glacier elevation class (% of landunit)', units='unitless') - - call ncd_def_spatial_var(ncid=ncid, varname='TOPO_GLC_MEC', xtype=xtype, & - lev1name='nglcec', & - long_name='mean elevation on glacier elevation classes', units='m') - - if ( outnc_3dglc ) then - call ncd_def_spatial_var(ncid=ncid, varname='PCT_GLC_MEC_GIC', xtype=xtype, & - lev1name='nglcec', & - long_name='percent smaller glaciers and ice caps for each glacier elevation class (% of landunit)', units='unitless') - - call ncd_def_spatial_var(ncid=ncid, varname='PCT_GLC_MEC_ICESHEET', xtype=xtype, & - lev1name='nglcec', & - long_name='percent ice sheet for each glacier elevation class (% of landunit)', units='unitless') - - call ncd_def_spatial_var(ncid=ncid, varname='PCT_GLC_GIC', xtype=xtype, & - long_name='percent ice caps/glaciers (% of landunit)', units='unitless') - - call ncd_def_spatial_var(ncid=ncid, varname='PCT_GLC_ICESHEET', xtype=xtype, & - long_name='percent ice sheet (% of landunit)', units='unitless') - - end if - - if ( outnc_3dglc ) then - call ncd_def_spatial_var(ncid=ncid, varname='PCT_GLC_MEC_GIC', xtype=xtype, & - lev1name='nglcec', & - long_name='percent smaller glaciers and ice caps for each glacier elevation class (% of landunit)', units='unitless') - - call ncd_def_spatial_var(ncid=ncid, varname='PCT_GLC_MEC_ICESHEET', xtype=xtype, & - lev1name='nglcec', & - long_name='percent ice sheet for each glacier elevation class (% of landunit)', units='unitless') - - call ncd_def_spatial_var(ncid=ncid, varname='PCT_GLC_GIC', xtype=xtype, & - long_name='percent ice caps/glaciers (% of landunit)', units='unitless') - - call ncd_def_spatial_var(ncid=ncid, varname='PCT_GLC_ICESHEET', xtype=xtype, & - long_name='percent ice sheet (% of landunit)', units='unitless') - - end if - - call ncd_def_spatial_var(ncid=ncid, varname='PCT_URBAN', xtype=xtype, & - lev1name='numurbl', & - long_name='percent urban for each density type', units='unitless') - - call ncd_def_spatial_var(ncid=ncid, varname='URBAN_REGION_ID', xtype=nf_int, & - long_name='urban region ID', units='unitless') - - call harvdata%getFieldsIdx( ind1D, ind2D ) - do j = 1, harvdata%num1Dfields() - call ncd_def_spatial_var(ncid=ncid, varname=mkharvest_fieldname(ind1D(j),constant=.true.), xtype=xtype, & - long_name=mkharvest_longname(ind1D(j)), units=mkharvest_units(ind1D(j)) ) - end do - do j = 1, harvdata%num2Dfields() - call ncd_def_spatial_var(ncid=ncid, varname=mkharvest_fieldname(ind2D(j),constant=.true.), xtype=xtype, & - lev1name=harvdata%getFieldsDim(ind2D(j)), & - long_name=mkharvest_longname(ind2D(j)), units=mkharvest_units(ind2D(j)) ) - end do - deallocate(ind1D, ind2D) - - else - - call harvdata%getFieldsIdx( ind1D, ind2D ) - do j = 1, harvdata%num1Dfields() - call ncd_def_spatial_var(ncid=ncid, varname=mkharvest_fieldname(ind1D(j),constant=.false.), xtype=xtype, & - lev1name='time', & - long_name=mkharvest_longname(ind1D(j)), units=mkharvest_units(ind1D(j)) ) - end do - do j = 1, harvdata%num2Dfields() - call ncd_def_spatial_var(ncid=ncid, varname=mkharvest_fieldname(ind2D(j),constant=.false.), xtype=xtype, & - lev1name=harvdata%getFieldsDim(ind2D(j)), lev2name="time", & - long_name=mkharvest_longname(ind2D(j)), units=mkharvest_units(ind2D(j)) ) - end do - deallocate(ind1D, ind2D) - - end if ! .not. dynlanduse - - ! End of define mode - - call check_ret(nf_enddef(ncid), subname) - call check_ret(nf_close(ncid), subname) - - end subroutine mkfile - -end module mkfileMod diff --git a/tools/mksurfdata_map/src/mkgdpMod.F90 b/tools/mksurfdata_map/src/mkgdpMod.F90 deleted file mode 100644 index 138ddf1805..0000000000 --- a/tools/mksurfdata_map/src/mkgdpMod.F90 +++ /dev/null @@ -1,147 +0,0 @@ -module mkgdpMod - -!----------------------------------------------------------------------- -!BOP -! -! !MODULE: mkgdpMod -! -! !DESCRIPTION: -! make GDP from input GDP data -! -! !REVISION HISTORY: -! Author: Sam Levis and Bill Sacks -! -!----------------------------------------------------------------------- -! -! !USES: - use shr_kind_mod, only : r8 => shr_kind_r8 - use shr_sys_mod , only : shr_sys_flush - use mkdomainMod , only : domain_checksame - - implicit none - - private - -! !PUBLIC MEMBER FUNCTIONS: - public mkgdp ! regrid gdp data -! -!EOP -!=============================================================== -contains -!=============================================================== - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: mkgdp -! -! !INTERFACE: -subroutine mkgdp(ldomain, mapfname, datfname, ndiag, gdp_o) -! -! !DESCRIPTION: -! make GDP from input GDP data -! -! !USES: - use mkdomainMod, only : domain_type, domain_clean, domain_read - use mkgridmapMod - use mkncdio - use mkdiagnosticsMod, only : output_diagnostics_continuous - use mkchecksMod, only : min_bad -! -! !ARGUMENTS: - - implicit none - type(domain_type) , intent(in) :: ldomain - character(len=*) , intent(in) :: mapfname ! input mapping file name - character(len=*) , intent(in) :: datfname ! input data file name - integer , intent(in) :: ndiag ! unit number for diag out - real(r8) , intent(out):: gdp_o(:) ! output grid: GDP (x1000 1995 US$ per capita) -! -! !CALLED FROM: -! subroutine mksrfdat in module mksrfdatMod -! -! !REVISION HISTORY: -! Author: Sam Levis and Bill Sacks -! -! -! !LOCAL VARIABLES: -!EOP - type(gridmap_type) :: tgridmap - type(domain_type) :: tdomain ! local domain - real(r8), allocatable :: data_i(:) ! data on input grid - real(r8), allocatable :: frac_dst(:) ! output fractions - real(r8), allocatable :: mask_r8(:) ! float of tdomain%mask - integer :: ncid,varid ! input netCDF id's - integer :: ier ! error status - - real(r8), parameter :: min_valid = 0._r8 ! minimum valid value - - character(len=32) :: subname = 'mkgdp' -!----------------------------------------------------------------------- - - write (6,*) 'Attempting to make GDP.....' - call shr_sys_flush(6) - - ! ----------------------------------------------------------------- - ! Read domain and mapping information, check for consistency - ! ----------------------------------------------------------------- - - call domain_read(tdomain,datfname) - - call gridmap_mapread(tgridmap, mapfname ) - - ! Obtain frac_dst - allocate(frac_dst(ldomain%ns), stat=ier) - if (ier/=0) call abort() - call gridmap_calc_frac_dst(tgridmap, tdomain%mask, frac_dst) - - allocate(mask_r8(tdomain%ns), stat=ier) - if (ier/=0) call abort() - mask_r8 = tdomain%mask - call gridmap_check( tgridmap, mask_r8, frac_dst, subname ) - - call domain_checksame( tdomain, ldomain, tgridmap ) - - ! ----------------------------------------------------------------- - ! Open input file, allocate memory for input data - ! ----------------------------------------------------------------- - - write(6,*)'Open GDP file: ', trim(datfname) - call check_ret(nf_open(datfname, 0, ncid), subname) - - allocate(data_i(tdomain%ns), stat=ier) - if (ier/=0) call abort() - - ! ----------------------------------------------------------------- - ! Regrid gdp - ! ----------------------------------------------------------------- - - call check_ret(nf_inq_varid (ncid, 'gdp', varid), subname) - call check_ret(nf_get_var_double (ncid, varid, data_i), subname) - call gridmap_areaave_srcmask(tgridmap, data_i, gdp_o, nodata=0._r8, mask_src=tdomain%mask, frac_dst=frac_dst) - - ! Check validity of output data - if (min_bad(gdp_o, min_valid, 'gdp')) then - call abort() - end if - - call output_diagnostics_continuous(data_i, gdp_o, tgridmap, "GDP", "x1000 US$ per capita", ndiag, tdomain%mask, frac_dst) - - ! ----------------------------------------------------------------- - ! Close files and deallocate dynamic memory - ! ----------------------------------------------------------------- - - call check_ret(nf_close(ncid), subname) - call domain_clean(tdomain) - call gridmap_clean(tgridmap) - deallocate (data_i) - deallocate (frac_dst) - deallocate (mask_r8) - - write (6,*) 'Successfully made GDP' - write (6,*) - call shr_sys_flush(6) - -end subroutine mkgdp - -end module mkgdpMod diff --git a/tools/mksurfdata_map/src/mkglacierregionMod.F90 b/tools/mksurfdata_map/src/mkglacierregionMod.F90 deleted file mode 100644 index e644129ed3..0000000000 --- a/tools/mksurfdata_map/src/mkglacierregionMod.F90 +++ /dev/null @@ -1,139 +0,0 @@ -module mkglacierregionMod - - !----------------------------------------------------------------------- - !BOP - ! - ! !MODULE: mkglacierregionMod - ! - ! !DESCRIPTION: - ! make glacier region ID - ! - ! !REVISION HISTORY: - ! Author: Bill Sacks - ! - !----------------------------------------------------------------------- - ! - ! !USES: - use shr_kind_mod, only : r8 => shr_kind_r8 - use shr_sys_mod , only : shr_sys_flush - implicit none - - private - - ! !PUBLIC MEMBER FUNCTIONS: - public mkglacierregion ! make glacier region ID - ! - !EOP - -contains - - !----------------------------------------------------------------------- - subroutine mkglacierregion(ldomain, mapfname, datfname, ndiag, & - glacier_region_o) - ! - ! !DESCRIPTION: - ! Make glacier region ID - ! - ! Regridding is done by finding the max index that overlaps each destination cell, - ! without regard to the weight of overlap or dominance of each overlapping index. - ! - ! !USES: - use mkdomainMod, only : domain_type, domain_clean, domain_read, domain_checksame - use mkgridmapMod - use mkncdio - use mkindexmapMod, only : get_max_indices - use mkdiagnosticsMod, only : output_diagnostics_index - use mkchecksMod, only : min_bad - ! - ! !ARGUMENTS: - type(domain_type), intent(in) :: ldomain - character(len=*) , intent(in) :: mapfname ! input mapping file name - character(len=*) , intent(in) :: datfname ! input data file name - integer , intent(in) :: ndiag ! unit number for diag out - integer , intent(out) :: glacier_region_o(:) ! glacier region - ! - ! !LOCAL VARIABLES: - type(gridmap_type) :: tgridmap - type(domain_type) :: tdomain ! local domain - integer, allocatable :: glacier_region_i(:) ! glacier region on input grid - real(r8), allocatable :: frac_dst(:) ! output fractions - real(r8), allocatable :: mask_r8(:) ! float of tdomain%mask - integer :: ncid,varid ! input netCDF id's - integer :: ier ! error status - integer :: max_region ! max region ID - - character(len=*), parameter :: subname = 'mkglacierregion' - !----------------------------------------------------------------------- - - write (6,*) 'Attempting to make glacier region .....' - call shr_sys_flush(6) - - ! ------------------------------------------------------------------------ - ! Read domain and mapping information, check for consistency - ! ------------------------------------------------------------------------ - - call domain_read(tdomain, datfname) - - call gridmap_mapread(tgridmap, mapfname) - - ! Obtain frac_dst - allocate(frac_dst(ldomain%ns), stat=ier) - if (ier/=0) call abort() - call gridmap_calc_frac_dst(tgridmap, tdomain%mask, frac_dst) - - allocate(mask_r8(tdomain%ns), stat=ier) - if (ier/=0) call abort() - mask_r8 = tdomain%mask - call gridmap_check(tgridmap, mask_r8, frac_dst, subname) - - call domain_checksame(tdomain, ldomain, tgridmap) - - ! ------------------------------------------------------------------------ - ! Open input file, allocate memory for input data - ! ------------------------------------------------------------------------ - - write (6,*) 'Open glacier region raw data file: ', trim(datfname) - call check_ret(nf_open(datfname, 0, ncid), subname) - - allocate(glacier_region_i(tdomain%ns), stat=ier) - if (ier/=0) call abort() - - ! ------------------------------------------------------------------------ - ! Regrid glacier_region - ! ------------------------------------------------------------------------ - - call check_ret(nf_inq_varid(ncid, 'GLACIER_REGION', varid), subname) - call check_ret(nf_get_var_int(ncid, varid, glacier_region_i), subname) - if (min_bad(glacier_region_i, 0, 'GLACIER_REGION')) then - call abort() - end if - - call get_max_indices( & - gridmap = tgridmap, & - src_array = glacier_region_i, & - dst_array = glacier_region_o, & - nodata = 0, & - mask_src = tdomain%mask) - - max_region = maxval(glacier_region_i) - call output_diagnostics_index(glacier_region_i, glacier_region_o, tgridmap, & - 'Glacier Region ID', 0, max_region, ndiag, mask_src=tdomain%mask, frac_dst=frac_dst) - - ! ------------------------------------------------------------------------ - ! Deallocate dynamic memory & other clean up - ! ------------------------------------------------------------------------ - - call check_ret(nf_close(ncid), subname) - call domain_clean(tdomain) - call gridmap_clean(tgridmap) - deallocate(glacier_region_i) - deallocate(frac_dst) - deallocate(mask_r8) - - write (6,*) 'Successfully made glacier region' - write (6,*) - call shr_sys_flush(6) - - end subroutine mkglacierregion - -end module mkglacierregionMod diff --git a/tools/mksurfdata_map/src/mkglcmecMod.F90 b/tools/mksurfdata_map/src/mkglcmecMod.F90 deleted file mode 100644 index 9fbad66689..0000000000 --- a/tools/mksurfdata_map/src/mkglcmecMod.F90 +++ /dev/null @@ -1,794 +0,0 @@ -module mkglcmecMod -!----------------------------------------------------------------------- -!BOP -! -! !MODULE: mkglcmecMod -! -! !DESCRIPTION: -! Make glacier multi-elevation class data -! -! !REVISION HISTORY: -! Author: Erik Kluzek, Mariana Vertenstein -! -!----------------------------------------------------------------------- -!!USES: - use shr_kind_mod, only : r8 => shr_kind_r8 - use shr_sys_mod , only : shr_sys_flush - use mkdomainMod , only : domain_checksame - implicit none - - private ! By default make data private -! -! !PUBLIC MEMBER FUNCTIONS: -! - public mkglcmecInit ! Initialization - public mkglcmec ! Set glacier multi-elevation class - public mkglacier ! Set percent glacier -! -! !PUBLIC DATA MEMBERS: -! - integer, public :: nglcec = 10 ! number of elevation classes for glaciers - real(r8), pointer :: elevclass(:) ! elevation classes -! -! !PRIVATE MEMBER FUNCTIONS: - private get_elevclass ! get elevation class index - private mean_elevation_vc ! get the elevation of a virtual column -!EOP -!=============================================================== -contains -!=============================================================== - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: mkglcmecInit -! -! !INTERFACE: -subroutine mkglcmecInit( elevclass_o ) -! -! !DESCRIPTION: -! Initialize of Make glacier multi-elevation class data -! !USES: -! -! !ARGUMENTS: - implicit none - real(r8), intent(OUT) :: elevclass_o(:) ! elevation classes -! -! !CALLED FROM: -! subroutine mksrfdat in module mksrfdatMod -! -! !REVISION HISTORY: -! Author: Erik Kluzek -! -! -! !LOCAL VARIABLES: -!EOP - character(len=32) :: subname = 'mkglcmecInit:: ' -!----------------------------------------------------------------------- - allocate( elevclass(nglcec+1) ) - - ! ----------------------------------------------------------------- - ! Define elevation classes, represents lower boundary of each class - ! ----------------------------------------------------------------- - - if ( nglcec == 36 )then - elevclass(:) = (/ 0., 200., 400., 600., 800., & - 1000., 1200., 1400., 1600., 1800., & - 2000., 2200., 2400., 2600., 2800., & - 3000., 3200., 3400., 3600., 3800., & - 4000., 4200., 4400., 4600., 4800., & - 5000., 5200., 5400., 5600., 5800., & - 6000., 6200., 6400., 6600., 6800., & - 7000., 10000./) - else if ( nglcec == 10 )then - elevclass(1) = 0. - elevclass(2) = 200. - elevclass(3) = 400. - elevclass(4) = 700. - elevclass(5) = 1000. - elevclass(6) = 1300. - elevclass(7) = 1600. - elevclass(8) = 2000. - elevclass(9) = 2500. - elevclass(10) = 3000. - elevclass(11) = 10000. - else if ( nglcec == 5 )then - elevclass(1) = 0. - elevclass(2) = 500. - elevclass(3) = 1000. - elevclass(4) = 1500. - elevclass(5) = 2000. - elevclass(6) = 10000. - else if ( nglcec == 3 )then - elevclass(1) = 0. - elevclass(2) = 1000. - elevclass(3) = 2000. - elevclass(4) = 10000. - else if ( nglcec == 1 )then - elevclass(1) = 0. - elevclass(2) = 10000. - else - write(6,*) subname//"ERROR:: nglcec must be 1, 3, 5, 10 or 36",& - " to work with CLM: " - call abort() - end if - - elevclass_o(:) = elevclass(:) - -end subroutine mkglcmecInit - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: mkglcmec -! -! !INTERFACE: -subroutine mkglcmec(ldomain, mapfname, & - datfname_fglacier, ndiag, & - pctglcmec_o, topoglcmec_o, & - pctglcmec_gic_o, pctglcmec_icesheet_o, & - pctglc_gic_o, pctglc_icesheet_o) -! -! !DESCRIPTION: -! make percent glacier on multiple elevation classes, mean elevation for each -! elevation class, and associated fields -! -! Note that the raw glacier data are specified by level, and thus implicitly include the -! necessary topo data for breaking pct glacier into elevation classes. Each level in the -! input data is assigned to an elevation (given by BIN_CENTERS in the input data). Thus, -! all of the input glacier in level 1 is treated as being at the same elevation, and -! likewise for each other level. These elevations are then used in assigning pct_glacier -! to the appropriate elevation class in the output data, as well as determining the mean -! topographic height of each elevation class in the output data. -! -! Note that the various percentages computed here are given as % of the glc_mec landunit. -! If the input glacier area is 0 for a given grid cell, this requires setting these % -! variables in an arbitrary way. -! -! !USES: - use shr_sys_mod, only : shr_sys_abort - use mkdomainMod, only : domain_type, domain_clean, domain_read - use mkgridmapMod - use mkvarpar - use mkutilsMod, only : slightly_below, slightly_above - use mkncdio - use mkvarctl , only : outnc_3dglc -! -! !ARGUMENTS: - implicit none - type(domain_type) , intent(in) :: ldomain - character(len=*) , intent(in) :: mapfname ! input mapping file name - character(len=*) , intent(in) :: datfname_fglacier ! raw glacier data - integer , intent(in) :: ndiag ! unit number for diag out - real(r8) , intent(out):: pctglcmec_o (:,:) ! % for each elevation class on output glacier grid (% of landunit) - real(r8) , intent(out):: topoglcmec_o(:,:) ! mean elevation for each elevation classs on output glacier grid - real(r8), optional, intent(out):: pctglcmec_gic_o(:,:) ! % glc gic on output grid, by elevation class (% of landunit) - real(r8), optional, intent(out):: pctglcmec_icesheet_o(:,:) ! % glc ice sheet on output grid, by elevation class (% of landunit) - real(r8), optional, intent(out):: pctglc_gic_o(:) ! % glc gic on output grid, summed across elevation classes (% of landunit) - real(r8), optional, intent(out):: pctglc_icesheet_o(:) ! % glc ice sheet on output grid, summed across elevation classes (% of landunit) -! -! !CALLED FROM: -! subroutine mksrfdat in module mksrfdatMod -! -! !REVISION HISTORY: -! Author: David Lawrence -! 7/12/11: Bill Sacks: substantial rewrite to use input topo and % glacier at same resolution -! 9/25/12: Bill Sacks: substantial rewrite to use new format of fglacier, which provides -! percent by elevation bin (thus the separate topo dataset is no longer needed -! in this routine) -! -! -! !LOCAL VARIABLES: -!EOP - type(domain_type) :: tdomain ! local domain - type(gridmap_type) :: tgridmap ! local gridmap - real(r8), allocatable :: pctglc_gic_i(:) ! input GIC percentage for a single level - real(r8), allocatable :: pctglc_icesheet_i(:) ! input icesheet percentage for a single level - real(r8), allocatable :: topoglcmec_unnorm_o(:,:) ! same as topoglcmec_o, but unnormalized - real(r8), allocatable :: pctglc_tot_o(:) ! total glacier cover for the grid cell - real(r8), allocatable :: frac_dst(:) ! output fractions - real(r8) :: topoice_i ! topographic height of this level - real(r8) :: pctglc_i ! input total pct glacier for a single level & single point - real(r8) :: wt, frac ! weighting factors for remapping - integer :: ndims ! number of dimensions in input variables - integer :: dim_lengths(nf_max_var_dims) ! lengths of dimensions in input variables - integer, allocatable :: starts(:), counts(:) ! start indices & counts for reading variable slices - integer :: ni,no,ns_o,nst,lev ! indices - integer :: n,m ! indices - integer :: ncid,dimid,varid ! input netCDF id's - integer :: nlev ! number of levels in input file - real(r8) :: glc_sum ! temporary - integer :: ier ! error status - logical :: errors ! error status - - real(r8), parameter :: eps = 2.e-5_r8 ! epsilon for error checks (note that we use a large-ish value - ! because data are stored as single-precision floats in the - ! raw dataset) - real(r8), parameter :: eps_small = 1.e-12_r8 ! epsilon for error checks that expect close match - character(len=32) :: subname = 'mkglcmec' -!----------------------------------------------------------------------- - - ! Initialize all output fields to zero - - pctglcmec_o(:,:) = 0. - topoglcmec_o(:,:) = 0. - if ( outnc_3dglc )then - if ( (.not. present(pctglcmec_gic_o)) .or. (.not. present(pctglcmec_icesheet_o)) .or. & - (.not. present(pctglc_gic_o) ) .or. (.not. present(pctglc_icesheet_o) ) )then - call shr_sys_abort( subname//' ERROR: 3D glacier fields were NOT sent in and they are required' ) - end if - pctglcmec_gic_o(:,:) = 0. - pctglcmec_icesheet_o(:,:) = 0. - pctglc_gic_o(:) = 0. - pctglc_icesheet_o(:) = 0. - end if - - ! Set number of output points - - ns_o = ldomain%ns - - write (6,*) 'Attempting to make percent elevation class ',& - 'and mean elevation for glaciers .....' - call shr_sys_flush(6) - - ! ----------------------------------------------------------------- - ! Read domain and dimension information from glacier raw data file - ! ----------------------------------------------------------------- - - call domain_read(tdomain,datfname_fglacier) - nst = tdomain%ns - - ! Read z dimension size - write (6,*) 'Open glacier file: ', trim(datfname_fglacier) - call check_ret(nf_open(datfname_fglacier, 0, ncid), subname) - ier = nf_inq_dimid (ncid, 'z', dimid) - if (ier /= NF_NOERR) then - write (6,*) trim(subname), ' ERROR: z dimension not found on glacier file:' - write (6,*) trim(datfname_fglacier) - write (6,*) 'Perhaps you are trying to use an old-format glacier file?' - write (6,*) '(prior to Sept., 2012)' - call abort() - end if - call check_ret(nf_inq_dimlen (ncid, dimid, nlev), subname) - - ! ----------------------------------------------------------------- - ! Read mapping data, check for consistency with domains - ! ----------------------------------------------------------------- - - ! Mapping for raw glacier -> model output grid - call gridmap_mapread(tgridmap, mapfname ) - - ! Error checks for domain and map consistencies - call domain_checksame( tdomain, ldomain, tgridmap ) - - ! ----------------------------------------------------------------- - ! Determine dimension lengths and create start & count arrays - ! for later reading one level at a time - ! ----------------------------------------------------------------- - - call get_dim_lengths(ncid, 'PCT_GLC_GIC', ndims, dim_lengths) - - allocate(starts(ndims), counts(ndims), stat=ier) - if (ier/=0) call abort() - - starts(1:ndims) = 1 - - ! We assume that the last dimension is the level dimension - counts(1:ndims-1) = dim_lengths(1:ndims-1) - counts(ndims) = 1 - - ! -------------------------------------------------------------------- - ! Compute fields on the output grid - ! -------------------------------------------------------------------- - - allocate(pctglc_gic_i(nst), pctglc_icesheet_i(nst), stat=ier) - if (ier/=0) call abort() - - allocate(topoglcmec_unnorm_o(ns_o,nglcec), stat=ier) - if (ier/=0) call abort() - - allocate(frac_dst(ns_o), stat=ier) - if (ier/=0) call abort() - - topoglcmec_unnorm_o(:,:) = 0. - - write(6,'(a,i4,a)',advance='no') 'Level (out of ', nlev, '): ' - - ! Obtain frac_dst - call gridmap_calc_frac_dst(tgridmap, tdomain%mask, frac_dst) - - do lev = 1, nlev - write(6,'(i4)',advance='no') lev - flush(6) - - ! Read this level's data - ! We assume that the last dimension is the level dimension - starts(ndims) = lev - call check_ret(nf_inq_varid (ncid, 'BIN_CENTERS', varid), subname) - call check_ret(nf_get_vara_double (ncid, varid, (/lev/), (/1/), topoice_i), subname) - call check_ret(nf_inq_varid (ncid, 'PCT_GLC_GIC', varid), subname) - call check_ret(nf_get_vara_double (ncid, varid, starts, counts, pctglc_gic_i), subname) - call check_ret(nf_inq_varid (ncid, 'PCT_GLC_ICESHEET', varid), subname) - call check_ret(nf_get_vara_double (ncid, varid, starts, counts, pctglc_icesheet_i), subname) - - ! Determine elevation class - m = get_elevclass(topoice_i) - if (m < 1 .or. m > nglcec) then - call abort() - end if - - do n = 1,tgridmap%ns - ni = tgridmap%src_indx(n) - no = tgridmap%dst_indx(n) - wt = tgridmap%wovr(n) * tdomain%mask(ni) - - ! fraction of this destination cell that is covered by source cells that are within the source landmask - frac = frac_dst(no) - - ! If frac == 0, then we can't do this, to avoid divide by 0. In this case, the - ! outputs remain equal to 0 (their initialized value). - if (frac > 0) then - pctglc_i = pctglc_gic_i(ni) + pctglc_icesheet_i(ni) - pctglcmec_o(no,m) = pctglcmec_o(no,m) + wt*pctglc_i / frac - if ( outnc_3dglc )then - pctglcmec_gic_o(no,m) = pctglcmec_gic_o(no,m) + wt*pctglc_gic_i(ni) / frac - pctglcmec_icesheet_o(no,m) = pctglcmec_icesheet_o(no,m) + wt*pctglc_icesheet_i(ni) / frac - end if - - ! note that, by weighting the following by pctglc_i, we are getting something - ! like the average topographic height over glaciated areas - NOT the average - ! topographic height of the entire grid cell - topoglcmec_unnorm_o(no,m) = topoglcmec_unnorm_o(no,m) + wt*pctglc_i*topoice_i / frac - end if - end do - end do - - ! Note: at this point, the various percentages are given as % of grid cell; below, we - ! renormalize these to be given as % of landunit. - - ! advance to next line (needed because of 'advance=no' writes above) - write(6,*) ' ' - - ! Close glacier input file - call check_ret(nf_close(ncid), subname) - - ! Normalize topoglcmec_o. To do this, note that pctglcmec_o(n,m) is equal to the sum of - ! the weights used in doing the weighted average of topoice_i (weight = - ! wt*pctglc_i/frac); hence pctglcmec_o(n,m) is the correct normalization factor - do no = 1,ns_o - do m = 1,nglcec - if (pctglcmec_o(no,m) > 0) then - topoglcmec_o(no,m) = topoglcmec_unnorm_o(no,m) / pctglcmec_o(no,m) - else - topoglcmec_o(no,m) = mean_elevation_vc(m) - end if - - ! Correct for rounding errors that put topoglcmec_o(no,m) slightly outside the - ! allowed bounds for this elevation class - if (slightly_below(topoglcmec_o(no,m), elevclass(m))) then - write(6,*) 'Warning: topoglcmec_o was slightly lower than lower bound; setting equal& - & to lower bound; for: ', no, m, topoglcmec_o(no,m), elevclass(m) - write(6,*) '(this is informational only, and probably just indicates rounding error)' - topoglcmec_o(no,m) = elevclass(m) - else if (slightly_above(topoglcmec_o(no,m), elevclass(m+1))) then - write(6,*) 'Warning: topoglcmec_o was slightly higher than upper bound; setting equal& - & to upper bound; for: ', no, m, topoglcmec_o(no,m), elevclass(m+1) - write(6,*) '(this is informational only, and probably just indicates rounding error)' - topoglcmec_o(no,m) = elevclass(m+1) - end if - end do - end do - - ! Renormalize percentages to be given as % of landunit rather than % of grid cell. - - allocate(pctglc_tot_o(ns_o), stat=ier) - if (ier/=0) call abort() - - do no = 1,ns_o - pctglc_tot_o(no) = sum(pctglcmec_o(no,:)) - - if (pctglc_tot_o(no) > 0._r8) then - pctglcmec_o(no,:) = pctglcmec_o(no,:) / pctglc_tot_o(no) * 100._r8 - if ( outnc_3dglc )then - pctglcmec_gic_o(no,:) = pctglcmec_gic_o(no,:) / pctglc_tot_o(no) * 100._r8 - pctglcmec_icesheet_o(no,:) = pctglcmec_icesheet_o(no,:) / pctglc_tot_o(no) * 100._r8 - end if - - else - ! Division of landunit is ambiguous. Apply the rule that all area is assigned to - ! the lowest elevation class, and all GIC. - pctglcmec_o(no,1) = 100._r8 - if ( outnc_3dglc )then - pctglcmec_gic_o(no,1) = 100._r8 - end if - end if - end do - - ! Set pctglc_gic_o to sum of pctglcmec_gic_o across elevation classes, and similarly for pctglc_icesheet_o - if ( outnc_3dglc )then - pctglc_gic_o = sum(pctglcmec_gic_o, dim=2) - pctglc_icesheet_o = sum(pctglcmec_icesheet_o, dim=2) - end if - - ! -------------------------------------------------------------------- - ! Perform various sanity checks - ! -------------------------------------------------------------------- - - errors = .false. - - ! Confirm that the sum over pctglcmec_o (from 1 to nglcec) is 100% - do no = 1,ns_o - glc_sum = sum(pctglcmec_o(no,:)) - if (abs(glc_sum - 100._r8) > eps_small) then - write(6,*)'glc_sum differs from 100% at no,pctglc= ',no,glc_sum - errors = .true. - end if - end do - - ! Confirm that GIC + ICESHEET = 100% - if ( outnc_3dglc )then - do no = 1,ns_o - if (abs((pctglc_gic_o(no) + pctglc_icesheet_o(no)) - 100._r8) > eps) then - write(6,*)'GIC + ICESHEET differs from 100% at no,pctglc_gic,pctglc_icesheet,lon,lat=', & - no,pctglc_gic_o(no),pctglc_icesheet_o(no),& - tgridmap%xc_dst(no),tgridmap%yc_dst(no) - errors = .true. - end if - end do - - ! Check that GIC + ICESHEET = total glacier at each elevation class - do m = 1, nglcec - do no = 1,ns_o - if (abs((pctglcmec_gic_o(no,m) + pctglcmec_icesheet_o(no,m)) - & - pctglcmec_o(no,m)) > eps) then - write(6,*)'GIC + ICESHEET differs from total GLC ' - write(6,*)'at no,m,pctglcmec,pctglcmec_gic,pctglcmec_icesheet = ' - write(6,*) no,m,pctglcmec_o(no,m),pctglcmec_gic_o(no,m),pctglcmec_icesheet_o(no,m) - errors = .true. - end if - end do - end do - end if - - - ! Error check: are all elevations within elevation class range - do no = 1,ns_o - do m = 1,nglcec - if (topoglcmec_o(no,m) < elevclass(m) .or. topoglcmec_o(no,m) > elevclass(m+1)) then - write(6,*) 'Error: mean elevation does not fall within elevation class ' - write(6,*) elevclass(m),elevclass(m+1),topoglcmec_o(no,m),m,no - errors = .true. - endif - end do - end do - - if (errors) then - call abort() - end if - - ! Deallocate dynamic memory - - call domain_clean(tdomain) - call gridmap_clean(tgridmap) - deallocate(pctglc_gic_i, pctglc_icesheet_i) - deallocate(topoglcmec_unnorm_o) - deallocate(pctglc_tot_o) - deallocate(frac_dst) - deallocate(starts, counts) - - write (6,*) 'Successfully made percent elevation class and mean elevation for glaciers' - write (6,*) - call shr_sys_flush(6) - -end subroutine mkglcmec - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: mkglacier -! -! !INTERFACE: -subroutine mkglacier(ldomain, mapfname, datfname, ndiag, zero_out, glac_o) -! -! !DESCRIPTION: -! make percent glacier -! -! In contrast to mkglcmec, this uses a "flat" PCT_GLACIER field (not separated by -! elevation class, and not separated into icesheet vs GIC). -! -! This simpler routine is sufficient for cases when we run without multiple elevation -! classes. This routine is also used when running with multiple elevation classes: we -! first regrid the flat PCT_GLACIER field, then later create the multiple elevation class -! data. This multi-step process makes it easier to do corrections on the total -! PCT_GLACIER, and make sure these corrections apply appropriately to the multi-level -! output. The assumption is that PCT_GLACIER is the sum of both PCT_GLC_GIC and -! PCT_GLC_ICESHEET across all elevation bins. -! -! !USES: - use mkdomainMod , only : domain_type, domain_clean, domain_read - use mkgridmapMod - use mkvarpar - use mkvarctl - use mkncdio -! -! !ARGUMENTS: - implicit none - type(domain_type), intent(in) :: ldomain - character(len=*) , intent(in) :: mapfname ! input mapping file name - character(len=*) , intent(in) :: datfname ! input data file name - integer , intent(in) :: ndiag ! unit number for diag out - logical , intent(in) :: zero_out ! if should zero glacier out - real(r8) , intent(out):: glac_o(:) ! output grid: %glacier -! -! !CALLED FROM: -! subroutine mksrfdat in module mksrfdatMod -! -! !REVISION HISTORY: -! Author: Mariana Vertenstein -! -! -! !LOCAL VARIABLES: -!EOP - type(gridmap_type) :: tgridmap - type(domain_type) :: tdomain ! local domain - real(r8), allocatable :: glac_i(:) ! input grid: percent glac - real(r8), allocatable :: frac_dst(:) ! output fractions - real(r8), allocatable :: mask_r8(:) ! float of tdomain%mask - real(r8) :: sum_fldi ! global sum of dummy input fld - real(r8) :: sum_fldo ! global sum of dummy output fld - real(r8) :: gglac_i ! input grid: global glac - real(r8) :: garea_i ! input grid: global area - real(r8) :: gglac_o ! output grid: global glac - real(r8) :: garea_o ! output grid: global area - integer :: ni,no,k,n,m,ns, ns_o ! indices - integer :: ncid,dimid,varid ! input netCDF id's - integer :: ier ! error status - real(r8) :: relerr = 0.00001 ! max error: sum overlap wts ne 1 - character(len=32) :: subname = 'mkglacier' -!----------------------------------------------------------------------- - - write (6,*) 'Attempting to make %glacier .....' - call shr_sys_flush(6) - - ! ----------------------------------------------------------------- - ! Read input file - ! ----------------------------------------------------------------- - - ! Obtain input grid info, read local fields - - call domain_read(tdomain,datfname) - ns = tdomain%ns - ns_o = ldomain%ns - allocate(glac_i(ns), & - frac_dst(ns_o), & - stat=ier) - if (ier/=0) call abort() - - write (6,*) 'Open glacier file: ', trim(datfname) - call check_ret(nf_open(datfname, 0, ncid), subname) - call check_ret(nf_inq_varid (ncid, 'PCT_GLACIER', varid), subname) - call check_ret(nf_get_var_double (ncid, varid, glac_i), subname) - call check_ret(nf_close(ncid), subname) - - ! Area-average percent cover on input grid to output grid - ! and correct according to land landmask - ! Note that percent cover is in terms of total grid area. - - if ( zero_out )then - - do no = 1, ns_o - glac_o(no) = 0. - enddo - - else - - call gridmap_mapread(tgridmap, mapfname ) - - ! Error checks for domain and map consistencies - call domain_checksame( tdomain, ldomain, tgridmap ) - - ! Obtain frac_dst - call gridmap_calc_frac_dst(tgridmap, tdomain%mask, frac_dst) - - ! Determine glac_o on output grid - - call gridmap_areaave_srcmask(tgridmap, glac_i, glac_o, nodata=0._r8, mask_src=tdomain%mask, frac_dst=frac_dst) - - do no = 1, ns_o - if (glac_o(no) < 1.) glac_o(no) = 0. - enddo - end if - - ! Check for conservation - - do no = 1, ns_o - if ((glac_o(no)) > 100.000001_r8) then - write (6,*) 'MKGLACIER error: glacier = ',glac_o(no), & - ' greater than 100.000001 for column, row = ',no - call shr_sys_flush(6) - call abort() - end if - enddo - - ! Some error checking and writing of global values before and after the regrid - - if ( .not. zero_out )then - - ! Global sum of output field -- must multiply by fraction of - ! output grid that is land as determined by input grid - - allocate(mask_r8(ns), stat=ier) - if (ier/=0) call abort() - mask_r8 = tdomain%mask - call gridmap_check( tgridmap, mask_r8, frac_dst, subname ) - - ! ----------------------------------------------------------------- - ! Error check2 - ! Compare global areas on input and output grids - ! ----------------------------------------------------------------- - - ! Input grid - - gglac_i = 0. - garea_i = 0. - do ni = 1, ns - garea_i = garea_i + tgridmap%area_src(ni)*re**2 - gglac_i = gglac_i + glac_i(ni)*(tgridmap%area_src(ni)/100.)*& - tdomain%mask(ni)*re**2 - end do - - ! Output grid - - gglac_o = 0. - garea_o = 0. - do no = 1, ns_o - garea_o = garea_o + tgridmap%area_dst(no)*re**2 - gglac_o = gglac_o + glac_o(no)*(tgridmap%area_dst(no)/100.)*& - frac_dst(no)*re**2 - end do - - ! Diagnostic output - - write (ndiag,*) - write (ndiag,'(1x,70a1)') ('=',k=1,70) - write (ndiag,*) 'Glacier Output' - write (ndiag,'(1x,70a1)') ('=',k=1,70) - - write (ndiag,*) - write (ndiag,'(1x,70a1)') ('.',k=1,70) - write (ndiag,2001) -2001 format (1x,'surface type input grid area output grid area'/ & - 1x,' 10**6 km**2 10**6 km**2 ') - write (ndiag,'(1x,70a1)') ('.',k=1,70) - write (ndiag,*) - write (ndiag,2002) gglac_i*1.e-06,gglac_o*1.e-06 - write (ndiag,2004) garea_i*1.e-06,garea_o*1.e-06 -2002 format (1x,'glaciers ',f14.3,f17.3) -2004 format (1x,'all surface ',f14.3,f17.3) - - end if - - ! Deallocate dynamic memory - - call domain_clean(tdomain) - if ( .not. zero_out )then - call gridmap_clean(tgridmap) - deallocate (glac_i, frac_dst, mask_r8) - end if - - write (6,*) 'Successfully made %glacier' - write (6,*) - call shr_sys_flush(6) - -end subroutine mkglacier - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: get_elevclass -! -! !INTERFACE: -integer function get_elevclass(topo, writewarn) -! -! !DESCRIPTION: -! Returns elevation class index (1..nglcec) given the topographic height. -! If topo is lower than the lowest elevation class, returns 0. -! If topo is higher than the highest elevation class, returns (nglcec+1). -! In either of the two latter cases, the function also writes a warning message, unless -! writewarn is present and false. -! -! !ARGUMENTS: - implicit none - real(r8), intent(in) :: topo ! topographic height (m) - logical, intent(in), optional :: writewarn ! should warning messages be written? (default: true) -! -! !REVISION HISTORY: -! Author: Bill Sacks -! -! !LOCAL VARIABLES: -!EOP - integer :: m - logical :: my_writewarn - character(len=32) :: subname = 'get_elevclass' -!----------------------------------------------------------------------- - - if (present(writewarn)) then - my_writewarn = writewarn - else - my_writewarn = .true. - end if - - if (topo < elevclass(1)) then - if (my_writewarn) then - write(6,*) 'WARNING in ', trim(subname) - write(6,*) 'topo out of bounds' - write(6,*) 'topo = ', topo - write(6,*) 'elevclass(1) = ', elevclass(1) - end if - get_elevclass = 0 - return - end if - - do m = 1, nglcec - if (topo < elevclass(m+1)) then - ! note that we already know that topo >= elevclass(m), otherwise we would have - ! returned earlier - get_elevclass = m - return - end if - end do - - if (my_writewarn) then - write(6,*) 'WARNING in ', trim(subname) - write(6,*) 'topo out of bounds' - write(6,*) 'topo = ', topo - write(6,*) 'elevclass(nglcec+1) = ', elevclass(nglcec+1) - end if - get_elevclass = nglcec+1 - -end function get_elevclass - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: mean_elevation_vc -! -! !INTERFACE: -real(r8) function mean_elevation_vc(class) -! -! !DESCRIPTION: -! For a virtual column (thus, a column that has no true elevation data), return the -! "mean" elevation of the given elevation class. -! -! !ARGUMENTS: - implicit none - integer, intent(in) :: class ! elevation class -! -! !REVISION HISTORY: -! Author: Bill Sacks -! -! !LOCAL VARIABLES: -!EOP - character(len=32) :: subname = 'mean_elevation_vc' -!----------------------------------------------------------------------- - - if (class < nglcec) then - mean_elevation_vc = 0.5_r8 * (elevclass(class) + elevclass(class+1)) - else if (class == nglcec) then - ! In the top elevation class; in this case, assignment of a "mean" elevation is - ! somewhat arbitrary - - if (nglcec > 1) then - mean_elevation_vc = 2.0_r8*elevclass(class) - elevclass(class-1) - else - ! entirely arbitrary - mean_elevation_vc = 1000._r8 - end if - else - write(6,*) 'ERROR in ', trim(subname), ': class out of bounds= ', class - call abort() - end if - -end function mean_elevation_vc - -end module mkglcmecMod diff --git a/tools/mksurfdata_map/src/mkgridmapMod.F90 b/tools/mksurfdata_map/src/mkgridmapMod.F90 deleted file mode 100644 index eeb5afdbb8..0000000000 --- a/tools/mksurfdata_map/src/mkgridmapMod.F90 +++ /dev/null @@ -1,915 +0,0 @@ -module mkgridmapMod -!----------------------------------------------------------------------- -!BOP -! -! !MODULE: mkgridmapMod -! -! !DESCRIPTION: -! Module containing 2-d global surface boundary data information -! -! !NOTES: -! Avoid using the frac_src and frac_dst found here, because they -! are read from mapping files, and we have generally moved to "nomask" -! mapping files. This means that mapping files now typically contain -! mask and frac equal to 1 everywhere. So now during remapping we apply the -! source masks found in the raw datasets and ignore the masks found in the -! mapping files. Exception: we continue to use a masked mapping file to regrid -! the 1-km topography. -! -! !USES: - use shr_kind_mod, only : r8 => shr_kind_r8 - - implicit none - private - -! !PUBLIC TYPES: - type gridmap_type - character(len=32) :: set ! If set or not - integer :: na ! size of source domain - integer :: nb ! size of destination domain - integer :: ns ! number of non-zero elements in matrix - real(r8), pointer :: yc_src(:) ! "degrees" - real(r8), pointer :: yc_dst(:) ! "degrees" - real(r8), pointer :: xc_src(:) ! "degrees" - real(r8), pointer :: xc_dst(:) ! "degrees" - real(R8), pointer :: area_src(:) ! area of a grid in map (radians) - real(R8), pointer :: area_dst(:) ! area of b grid in map (radians) - real(r8), pointer :: frac_src(:) ! "unitless" - real(r8), pointer :: frac_dst(:) ! "unitless" - integer , pointer :: src_indx(:) ! correpsonding column index - integer , pointer :: dst_indx(:) ! correpsonding row index - real(r8), pointer :: wovr(:) ! wt of overlap input cell - end type gridmap_type - public :: gridmap_type -! -! !PUBLIC MEMBER FUNCTIONS: - public :: gridmap_setptrs ! Set pointers to gridmap data - public :: for_test_create_gridmap ! Set a gridmap directly, for testing - public :: gridmap_mapread ! Read in gridmap - public :: gridmap_check ! Check validity of a gridmap - public :: gridmap_calc_frac_dst ! Obtain frac_dst - public :: gridmap_areaave_no_srcmask ! do area average without passing mask - public :: gridmap_areaave_srcmask ! do area average with mask passed - public :: gridmap_areaave_scs ! area average, but multiply by ratio of source over destination weight - public :: gridmap_areastddev ! do area-weighted standard deviation - public :: gridmap_clean ! Clean and deallocate a gridmap structure -! -! -! !REVISION HISTORY: -! Author Mariana Vertenstein - - ! questions - how does the reverse mapping occur - ! is mask_dst read in - and what happens if this is very different - ! from frac_dst which is calculated by mapping frac_src? - ! in frac - isn't grid1_frac always 1 or 0? - - ! !PRIVATE MEMBER FUNCTIONS: - private :: set_gridmap_var - private :: gridmap_checkifset - - interface set_gridmap_var - module procedure set_gridmap_var_r8 - module procedure set_gridmap_var_int - end interface set_gridmap_var - - character(len=32), parameter :: isSet = "gridmap_IsSet" - -! -!EOP -!------------------------------------------------------------------------------ -contains - -!------------------------------------------------------------------------------ -!BOP -! -! !IROUTINE: gridmap_setptrs -! -! !INTERFACE: - subroutine gridmap_setptrs(gridmap, nsrc, ndst, ns, yc_src, yc_dst, & - xc_src, xc_dst, & - frac_src, frac_dst, src_indx, dst_indx ) -! -! !DESCRIPTION: -! This subroutine assigns pointers to some of the map type data. -! -! !ARGUMENTS: - implicit none - type(gridmap_type), intent(in) :: gridmap ! mapping data - integer, optional :: nsrc ! size of source domain - integer, optional :: ndst ! size of destination domain - integer, optional :: ns ! number of non-zero elements in matrix - integer, optional, pointer :: dst_indx(:) ! Destination index - integer, optional, pointer :: src_indx(:) ! Destination index - real(r8), optional, pointer :: yc_src(:) ! "degrees" - real(r8), optional, pointer :: yc_dst(:) ! "degrees" - real(r8), optional, pointer :: xc_src(:) ! "degrees" - real(r8), optional, pointer :: xc_dst(:) ! "degrees" - real(r8), optional, pointer :: frac_src(:) ! "unitless" - real(r8), optional, pointer :: frac_dst(:) ! "unitless" -! -! !REVISION HISTORY: -! Created by Erik Kluzek -! -! !LOCAL VARIABLES: -!EOP -!------------------------------------------------------------------------------ - character(*),parameter :: subName = '(gridmap_setptrs) ' - - call gridmap_checkifset( gridmap, subname ) - if ( present(nsrc) ) nsrc = gridmap%na - if ( present(ndst) ) ndst = gridmap%nb - if ( present(ns) ) ns = gridmap%ns - if ( present(yc_src) ) yc_src => gridmap%yc_src - if ( present(xc_src) ) xc_src => gridmap%xc_src - if ( present(frac_src) ) frac_src => gridmap%frac_src - if ( present(yc_dst) ) yc_dst => gridmap%yc_dst - if ( present(xc_dst) ) xc_dst => gridmap%xc_dst - if ( present(frac_dst) ) frac_dst => gridmap%frac_dst - if ( present(dst_indx) ) dst_indx => gridmap%dst_indx - if ( present(src_indx) ) src_indx => gridmap%src_indx - end subroutine gridmap_setptrs - -!------------------------------------------------------------------------------ -!BOP -! -! !IROUTINE: gridmap_mapread -! -! !INTERFACE: - subroutine gridmap_mapread(gridmap, fileName) -! -! !DESCRIPTION: -! This subroutine reads in the map file -! -! !USES: - use mkncdio, only : nf_open, nf_close, nf_strerror - use mkncdio, only : nf_inq_dimid, nf_inq_dimlen - use mkncdio, only : nf_inq_varid, nf_get_var_double, nf_get_var_int - use mkncdio, only : NF_NOWRITE, NF_NOERR - use mkncdio, only : convert_latlon -! -! !ARGUMENTS: - implicit none - type(gridmap_type), intent(out) :: gridmap ! mapping data - character(len=*) , intent(in) :: filename ! netCDF file to read -! -! !REVISION HISTORY: -! Created by Mariana Vertenstein -! -! !LOCAL VARIABLES: - integer :: n ! generic loop indicies - integer :: na ! size of source domain - integer :: nb ! size of destination domain - integer :: igrow ! aVect index for matrix row - integer :: igcol ! aVect index for matrix column - integer :: iwgt ! aVect index for matrix element - integer :: iarea ! aVect index for area - - - character,allocatable :: str(:) ! variable length char string - character(len=256) :: attstr ! netCDF attribute name string - integer :: rcode ! netCDF routine return code - integer :: fid ! netCDF file ID - integer :: vid ! netCDF variable ID - integer :: did ! netCDF dimension ID - integer :: ns ! size of array - - real(r8), parameter :: tol = 1.0e-4_r8 ! tolerance for checking that mapping data - ! are within expected bounds - - !--- formats --- - character(*),parameter :: subName = '(gridmap_map_read) ' - character(*),parameter :: F00 = '("(gridmap_map_read) ",4a)' - character(*),parameter :: F01 = '("(gridmap_map_read) ",2(a,i7))' -!EOP -!------------------------------------------------------------------------------ - - !------------------------------------------------------------------------------- - ! - !------------------------------------------------------------------------------- - - write(6,F00) "reading mapping matrix data..." - - ! open & read the file - write(6,F00) "* file name : ",trim(fileName) - - rcode = nf_open(filename ,NF_NOWRITE, fid) - if (rcode /= NF_NOERR) write(6,F00) nf_strerror(rcode) - - !--- allocate memory & get matrix data ---------- - rcode = nf_inq_dimid (fid, 'n_s', did) ! size of sparse matrix - rcode = nf_inq_dimlen(fid, did , gridmap%ns) - rcode = nf_inq_dimid (fid, 'n_a', did) ! size of input vector - rcode = nf_inq_dimlen(fid, did , gridmap%na) - rcode = nf_inq_dimid (fid, 'n_b', did) ! size of output vector - rcode = nf_inq_dimlen(fid, did , gridmap%nb) - - write(6,*) "* matrix dimensions rows x cols :",gridmap%na,' x',gridmap%nb - write(6,*) "* number of non-zero elements: ",gridmap%ns - - ns = gridmap%ns - na = gridmap%na - nb = gridmap%nb - allocate(gridmap%wovr(ns) , & - gridmap%src_indx(ns), & - gridmap%dst_indx(ns), & - gridmap%area_src(na), & - gridmap%frac_src(na), & - gridmap%area_dst(nb), & - gridmap%frac_dst(nb), & - gridmap%xc_dst(nb), & - gridmap%yc_dst(nb), & - gridmap%xc_src(na), & - gridmap%yc_src(na), stat=rcode) - if (rcode /= 0) then - write(6,*) SubName//' ERROR: allocate gridmap' - call abort() - endif - - rcode = nf_inq_varid(fid,'S' ,vid) - rcode = nf_get_var_double(fid,vid ,gridmap%wovr) - if (rcode /= NF_NOERR) write(6,F00) nf_strerror(rcode) - - rcode = nf_inq_varid(fid,'row',vid) - rcode = nf_get_var_int(fid, vid ,gridmap%dst_indx) - if (rcode /= NF_NOERR) write(6,F00) nf_strerror(rcode) - - rcode = nf_inq_varid(fid,'col',vid) - rcode = nf_get_var_int(fid, vid, gridmap%src_indx) - if (rcode /= NF_NOERR) write(6,F00) nf_strerror(rcode) - - rcode = nf_inq_varid(fid,'area_a',vid) - rcode = nf_get_var_double(fid, vid, gridmap%area_src) - if (rcode /= NF_NOERR) write(6,F00) nf_strerror(rcode) - - rcode = nf_inq_varid(fid,'area_b',vid) - rcode = nf_get_var_double(fid, vid, gridmap%area_dst) - if (rcode /= NF_NOERR) write(6,F00) nf_strerror(rcode) - - rcode = nf_inq_varid(fid,'frac_a',vid) - rcode = nf_get_var_double(fid, vid, gridmap%frac_src) - if (rcode /= NF_NOERR) write(6,F00) nf_strerror(rcode) - if ( any(gridmap%frac_src(:) < 0.0_r8 .or. gridmap%frac_src > (1.0_r8 + tol)) )then - write(6,*) SubName//' ERROR: frac_src out of bounds' - write(6,*) 'max = ', maxval(gridmap%frac_src), ' min = ', minval(gridmap%frac_src) - call abort() - end if - - rcode = nf_inq_varid(fid,'frac_b',vid) - rcode = nf_get_var_double(fid, vid, gridmap%frac_dst) - if (rcode /= NF_NOERR) write(6,F00) nf_strerror(rcode) - if ( any(gridmap%frac_dst(:) < 0.0_r8 .or. gridmap%frac_dst > (1.0_r8 + tol)) )then - write(6,*) SubName//' ERROR: frac_dst out of bounds' - write(6,*) 'max = ', maxval(gridmap%frac_dst), ' min = ', minval(gridmap%frac_dst) - call abort() - end if - - rcode = nf_inq_varid(fid,'xc_a',vid) - rcode = nf_get_var_double(fid, vid, gridmap%xc_src) - if (rcode /= NF_NOERR) write(6,F00) nf_strerror(rcode) - call convert_latlon(fid, 'xc_a', gridmap%xc_src) - - rcode = nf_inq_varid(fid,'yc_a',vid) - rcode = nf_get_var_double(fid, vid, gridmap%yc_src) - if (rcode /= NF_NOERR) write(6,F00) nf_strerror(rcode) - call convert_latlon(fid, 'yc_a', gridmap%yc_src) - - rcode = nf_inq_varid(fid,'xc_b',vid) - rcode = nf_get_var_double(fid, vid, gridmap%xc_dst) - if (rcode /= NF_NOERR) write(6,F00) nf_strerror(rcode) - call convert_latlon(fid, 'xc_b', gridmap%xc_dst) - - rcode = nf_inq_varid(fid,'yc_b',vid) - rcode = nf_get_var_double(fid, vid, gridmap%yc_dst) - if (rcode /= NF_NOERR) write(6,F00) nf_strerror(rcode) - call convert_latlon(fid, 'yc_b', gridmap%yc_dst) - - rcode = nf_close(fid) - - gridmap%set = IsSet - - end subroutine gridmap_mapread - -!========================================================================== - - !----------------------------------------------------------------------- - subroutine for_test_create_gridmap(gridmap, na, nb, ns, & - src_indx, dst_indx, wovr, & - frac_src, frac_dst, area_src, area_dst, & - xc_src, xc_dst, yc_src, yc_dst) - ! - ! !DESCRIPTION: - ! Creates a gridmap object directly from inputs - ! - ! This is meant for testing - ! - ! !ARGUMENTS: - type(gridmap_type), intent(out) :: gridmap - integer, intent(in) :: na - integer, intent(in) :: nb - integer, intent(in) :: ns - integer, intent(in) :: src_indx(:) - integer, intent(in) :: dst_indx(:) - real(r8), intent(in) :: wovr(:) - - ! If not provided, mask and frac values are set to 1 everywhere - real(r8), intent(in), optional :: frac_src(:) - real(r8), intent(in), optional :: frac_dst(:) - - ! If not provided, area values are set to a constant value everywhere - real(r8), intent(in), optional :: area_src(:) - real(r8), intent(in), optional :: area_dst(:) - - ! If not provided, xc and yc values are set to 0 everywhere - real(r8), intent(in), optional :: xc_src(:) - real(r8), intent(in), optional :: xc_dst(:) - real(r8), intent(in), optional :: yc_src(:) - real(r8), intent(in), optional :: yc_dst(:) - - ! - ! !LOCAL VARIABLES: - - character(len=*), parameter :: subname = 'for_test_create_gridmap' - !----------------------------------------------------------------------- - - ! ------------------------------------------------------------------------ - ! Error checking on sizes of arrays - ! ------------------------------------------------------------------------ - call check_input_size('src_indx', size(src_indx), ns) - call check_input_size('dst_indx', size(dst_indx), ns) - call check_input_size('wovr', size(wovr), ns) - - if (present(frac_src)) then - call check_input_size('frac_src', size(frac_src), na) - end if - if (present(area_src)) then - call check_input_size('area_src', size(area_src), na) - end if - if (present(xc_src)) then - call check_input_size('xc_src', size(xc_src), na) - end if - if (present(yc_src)) then - call check_input_size('yc_src', size(yc_src), na) - end if - - if (present(frac_dst)) then - call check_input_size('frac_dst', size(frac_dst), nb) - end if - if (present(area_dst)) then - call check_input_size('area_dst', size(area_dst), nb) - end if - if (present(xc_dst)) then - call check_input_size('xc_dst', size(xc_dst), nb) - end if - if (present(yc_dst)) then - call check_input_size('yc_dst', size(yc_dst), nb) - end if - - ! ------------------------------------------------------------------------ - ! Create gridmap object - ! ------------------------------------------------------------------------ - - gridmap%na = na - gridmap%nb = nb - gridmap%ns = ns - - allocate(gridmap%src_indx(ns)) - gridmap%src_indx = src_indx - allocate(gridmap%dst_indx(ns)) - gridmap%dst_indx = dst_indx - allocate(gridmap%wovr(ns)) - gridmap%wovr = wovr - - allocate(gridmap%frac_src(na)) - call set_gridmap_var(gridmap%frac_src, 1._r8, frac_src) - allocate(gridmap%frac_dst(nb)) - call set_gridmap_var(gridmap%frac_dst, 1._r8, frac_dst) - - allocate(gridmap%yc_src(na)) - call set_gridmap_var(gridmap%yc_src, 0._r8, yc_src) - allocate(gridmap%yc_dst(nb)) - call set_gridmap_var(gridmap%yc_dst, 0._r8, yc_dst) - allocate(gridmap%xc_src(na)) - call set_gridmap_var(gridmap%xc_src, 0._r8, xc_src) - allocate(gridmap%xc_dst(nb)) - call set_gridmap_var(gridmap%xc_dst, 0._r8, xc_dst) - allocate(gridmap%area_src(na)) - call set_gridmap_var(gridmap%area_src, 0._r8, area_src) - allocate(gridmap%area_dst(nb)) - call set_gridmap_var(gridmap%area_dst, 0._r8, area_dst) - - gridmap%set = isSet - - contains - subroutine check_input_size(varname, actual_size, expected_size) - character(len=*), intent(in) :: varname - integer, intent(in) :: actual_size - integer, intent(in) :: expected_size - - if (actual_size /= expected_size) then - write(6,*) subname, ' ERROR: ', trim(varname), ' wrong size: actual, expected = ', & - actual_size, expected_size - call abort() - end if - end subroutine check_input_size - - end subroutine for_test_create_gridmap - - subroutine set_gridmap_var_r8(var, default_val, input_val) - ! Convenience subroutine to set a variable to an optional input or a default value - real(r8), intent(out) :: var(:) - real(r8), intent(in) :: default_val - real(r8), intent(in), optional :: input_val(:) - - if (present(input_val)) then - var = input_val - else - var = default_val - end if - end subroutine set_gridmap_var_r8 - - subroutine set_gridmap_var_int(var, default_val, input_val) - ! Convenience subroutine to set a variable to an optional input or a default value - integer, intent(out) :: var(:) - integer, intent(in) :: default_val - integer, intent(in), optional :: input_val(:) - - if (present(input_val)) then - var = input_val - else - var = default_val - end if - end subroutine set_gridmap_var_int - -!------------------------------------------------------------------------------ -!BOP -! -! !IROUTINE: gridmap_check -! -! !INTERFACE: - subroutine gridmap_check(gridmap, mask_src, frac_dst, caller) -! -! !DESCRIPTION: -! Check validity of a gridmap -! Aborts if there are any errors -! -! !USES: - use mkvarctl, only : mksrf_gridtype - use mkvarpar, only : re -! -! !ARGUMENTS: - implicit none - type(gridmap_type) , intent(in) :: gridmap ! mapping data - real(r8), intent(in) :: mask_src(:) ! input mask; could be declared integer but for the argument passed from subr. mktopostats - real(r8), intent(in) :: frac_dst(:) ! output fractions - character(len=*) , intent(in) :: caller ! calling subroutine (used for error messages) -! -! !REVISION HISTORY: -! Created by Bill Sacks -! -! !LOCAL VARIABLES: - real(r8) :: sum_area_i ! global sum of input area - real(r8) :: sum_area_o ! global sum of output area - integer :: ni,no,ns_i,ns_o ! indices - - real(r8), parameter :: relerr = 0.00001 ! max error: sum overlap wts ne 1 - character(len=*), parameter :: subname = 'gridmap_check' -!EOP -!------------------------------------------------------------------------------ - - ns_i = gridmap%na - ns_o = gridmap%nb - - ! ----------------------------------------------------------------- - ! Error check prep - ! Global sum of output area -- must multiply by fraction of - ! output grid that is land as determined by input grid - ! ----------------------------------------------------------------- - - sum_area_i = 0.0_r8 - do ni = 1,ns_i - sum_area_i = sum_area_i + gridmap%area_src(ni)*mask_src(ni)*re**2 - enddo - - sum_area_o = 0. - do no = 1,ns_o - sum_area_o = sum_area_o + gridmap%area_dst(no)*frac_dst(no)*re**2 - end do - - ! ----------------------------------------------------------------- - ! Error check1 - ! Compare global sum_area_i to global sum_area_o. - ! ----------------------------------------------------------------- - - if ( trim(mksrf_gridtype) == 'global' ) then - if ( abs(sum_area_o/sum_area_i-1.) > relerr ) then - write (6,*) subname//' ERROR from '//trim(caller)//': mapping areas not conserved' - write (6,'(a30,e20.10)') 'global sum output field = ',sum_area_o - write (6,'(a30,e20.10)') 'global sum input field = ',sum_area_i - call abort() - end if - end if - - end subroutine gridmap_check - - -!========================================================================== - -!------------------------------------------------------------------------------ -!BOP -! -! !IROUTINE: gridmap_areaave_scs -! -! !INTERFACE: - subroutine gridmap_areaave_scs (gridmap, src_array, dst_array, nodata, src_wt, dst_wt, frac_dst) -! -! !DESCRIPTION: -! This subroutine does a simple area average, but multiplies by the ratio of the source over -! the destination weight. Sets to zero if destination weight is zero. -! -! The src_wt must be multiplied by tdomain%mask to maintain consistency with the -! incoming frac_dst. -! -! Called by subroutine mkpft. -! -! !ARGUMENTS: - implicit none - type(gridmap_type) , intent(in) :: gridmap ! gridmap data - real(r8), intent(in) :: src_array(:) - real(r8), intent(out):: dst_array(:) - real(r8), intent(in) :: nodata ! value to apply where there are no input data - real(r8), intent(in) :: src_wt(:) ! Source weights - real(r8), intent(in) :: dst_wt(:) ! Destination weights - real(r8), intent(in) :: frac_dst(:) ! Output grid weights - -! -! !REVISION HISTORY: -! Created by Mariana Vertenstein, moditied by Sean Swenson -! -! !LOCAL VARIABLES: - integer :: n,ns,ni,no - real(r8):: wt,frac,swt,dwt - real(r8), allocatable :: sum_weights(:) ! sum of weights on the output grid - character(*),parameter :: subName = '(gridmap_areaave_scs) ' -!EOP -!------------------------------------------------------------------------------ - - ! Error check inputs and initialize local variables - - if (size(frac_dst) /= size(dst_array)) then - write(6,*) subname//' ERROR: incorrect size of frac_dst' - write(6,*) 'size(frac_dst) = ', size(frac_dst) - write(6,*) 'size(dst_array) = ', size(dst_array) - call abort() - end if - - call gridmap_checkifset( gridmap, subname ) - allocate(sum_weights(size(dst_array))) - sum_weights = 0._r8 - dst_array = 0._r8 - - do n = 1,gridmap%ns - ni = gridmap%src_indx(n) - no = gridmap%dst_indx(n) - wt = gridmap%wovr(n) - frac = frac_dst(no) - swt = src_wt(ni) - dwt = dst_wt(no) - wt = wt * swt - if(dwt > 0._r8) then - wt = wt / dwt - else - wt = 0._r8 - endif - if (frac > 0.) then - dst_array(no) = dst_array(no) + wt * src_array(ni)/frac - sum_weights(no) = sum_weights(no) + wt - end if - end do - - where (sum_weights == 0._r8) - dst_array = nodata - end where - - deallocate(sum_weights) - - end subroutine gridmap_areaave_scs - -!========================================================================== - -!========================================================================== - -!------------------------------------------------------------------------------ -!BOP -! -! !IROUTINE: gridmap_areaave_srcmask -! -! !INTERFACE: - subroutine gridmap_areaave_srcmask (gridmap, src_array, dst_array, nodata, mask_src, frac_dst) -! -! !DESCRIPTION: -! This subroutine does an area average with the source mask -! -! !NOTES: -! We have generally moved to "nomask" mapping files. This means that mapping -! files now typically contain mask and frac equal to 1 everywhere. So now during -! remapping we apply the source masks found in the raw datasets and ignore the -! masks found in the mapping files. Exception: we continue to use a masked -! mapping file to regrid the 1-km topography. -! -! !ARGUMENTS: - implicit none - type(gridmap_type) , intent(in) :: gridmap ! gridmap data - real(r8), intent(in) :: src_array(:) - real(r8), intent(out):: dst_array(:) - real(r8), intent(in) :: nodata ! value to apply where there are no input data - integer, intent(in) :: mask_src(:) - real(r8), intent(in) :: frac_dst(:) -! -! !REVISION HISTORY: -! Created by Mariana Vertenstein -! -! !LOCAL VARIABLES: - integer :: n,ns,ni,no - real(r8):: wt - character(*),parameter :: subName = '(gridmap_areaave_srcmask) ' -!EOP -!------------------------------------------------------------------------------ - ! Error check inputs and initialize local variables - - ns = size(dst_array) - if (size(frac_dst) /= ns) then - write(6,*) subname//' ERROR: incorrect size of frac_dst' - write(6,*) 'size(frac_dst) = ', size(frac_dst) - write(6,*) 'size(dst_array) = ', ns - call abort() - end if - if (size(mask_src) /= size(src_array)) then - write(6,*) subname//' ERROR: incorrect size of mask_src' - write(6,*) 'size(mask_src) = ', size(mask_src) - write(6,*) 'size(src_array) = ', size(src_array) - call abort() - end if - - call gridmap_checkifset( gridmap, subname ) - - dst_array = 0._r8 - do n = 1,gridmap%ns - ni = gridmap%src_indx(n) - no = gridmap%dst_indx(n) - wt = gridmap%wovr(n) - if (mask_src(ni) > 0) then - dst_array(no) = dst_array(no) + wt*mask_src(ni)*src_array(ni)/frac_dst(no) - end if - end do - - where (frac_dst == 0._r8) - dst_array = nodata - end where - - end subroutine gridmap_areaave_srcmask - -!========================================================================== - -!------------------------------------------------------------------------------ -!BOP -! -! !IROUTINE: gridmap_areastddev -! -! !INTERFACE: - subroutine gridmap_areastddev (gridmap, src_array, dst_array, nodata) -! -! !DESCRIPTION: -! Computes area-weighted standard deviation -! -! We use the definition of standard deviation that applies if you measure the full -! population (as opposed to the unbiased standard deviation that should be used when -! sampling a subset of the full population). (This is equivalent to using 1/N rather than -! 1/(N-1).) This makes sense if we assume that the underlying values are constant -! throughout each source grid cell -- in that case, we know the full population as long as -! we know the values in all source grid cells, which is generally the case. -! -! The formula is from -! (accessed 3-4-13). -! -! !ARGUMENTS: - implicit none - type(gridmap_type) , intent(in) :: gridmap ! gridmap data - real(r8), intent(in) :: src_array(:) - real(r8), intent(out):: dst_array(:) - real(r8), intent(in) :: nodata ! value to apply where there are no input data -! -! !REVISION HISTORY: -! Created by Bill Sacks -! -! !LOCAL VARIABLES: - integer :: n,ni,no - integer :: ns_o ! number of output points - real(r8):: wt ! weight of overlap - real(r8), allocatable :: weighted_means(:) ! weighted mean on the output grid - real(r8), allocatable :: sum_weights(:) ! sum of weights on the output grid - character(*),parameter :: subName = '(gridmap_areastddev) ' -!EOP -!------------------------------------------------------------------------------ - call gridmap_checkifset( gridmap, subname ) - - ns_o = size(dst_array) - allocate(weighted_means(ns_o)) - - ! Subr. gridmap_areaave_no_srcmask should NOT be used in general. We have - ! kept it to support the rare raw data files for which we have masking on - ! the mapping file and, therefore, we do not explicitly pass the src_mask - ! as an argument. In general, users are advised to use subroutine - ! gridmap_areaave_srcmask. - call gridmap_areaave_no_srcmask(gridmap, src_array, weighted_means, nodata=0._r8) - - ! WJS (3-5-13): I believe that sum_weights should be the same as gridmap%frac_dst, - ! but I'm not positive of this, so we compute it explicitly to be safe - allocate(sum_weights(ns_o)) - sum_weights(:) = 0._r8 - dst_array(:) = 0._r8 - do n = 1,gridmap%ns - ni = gridmap%src_indx(n) - no = gridmap%dst_indx(n) - wt = gridmap%wovr(n) - ! The following accumulates the numerator of the weighted sigma-squared - dst_array(no) = dst_array(no) + wt * (src_array(ni) - weighted_means(no))**2 - sum_weights(no) = sum_weights(no) + wt - end do - - do no = 1,ns_o - if (sum_weights(no) > 0._r8) then - dst_array(no) = sqrt(dst_array(no)/sum_weights(no)) - else - dst_array(no) = nodata - end if - end do - - deallocate(weighted_means, sum_weights) - - end subroutine gridmap_areastddev - -!========================================================================== - -!------------------------------------------------------------------------------ -!BOP -! -! !IROUTINE: gridmap_clean -! -! !INTERFACE: - subroutine gridmap_clean(gridmap) -! -! !DESCRIPTION: -! This subroutine deallocates the gridmap type -! -! !ARGUMENTS: - implicit none - type(gridmap_type), intent(inout) :: gridmap -! -! !REVISION HISTORY: -! Created by Mariana Vertenstein -! -! !LOCAL VARIABLES: - character(len=*), parameter :: subName = "gridmap_clean" - integer ier ! error flag -!EOP -!------------------------------------------------------------------------------ - if ( gridmap%set .eq. IsSet )then - deallocate(gridmap%wovr , & - gridmap%src_indx, & - gridmap%dst_indx, & - gridmap%area_src, & - gridmap%area_dst, & - gridmap%frac_src, & - gridmap%frac_dst, & - gridmap%xc_src, & - gridmap%yc_src, stat=ier) - if (ier /= 0) then - write(6,*) SubName//' ERROR: deallocate gridmap' - call abort() - endif - else - write(6,*) SubName//' Warning: calling '//trim(subName)//' on unallocated gridmap' - end if - gridmap%set = "NOT-set" - - end subroutine gridmap_clean - -!========================================================================== - - subroutine gridmap_checkifset( gridmap, subname ) - - implicit none - type(gridmap_type), intent(in) :: gridmap - character(len=*), intent(in) :: subname - - if ( gridmap%set .ne. IsSet )then - write(6,*) SubName//' ERROR: gridmap NOT set yet, run gridmap_mapread first' - call abort() - end if - end subroutine gridmap_checkifset - -!========================================================================== - -!------------------------------------------------------------------------------ -!BOP -! -! !IROUTINE: gridmap_calc_frac_dst -! -! !INTERFACE: - subroutine gridmap_calc_frac_dst(gridmap, mask_src, frac_dst) -! -! !DESCRIPTION: -! This subroutine calculates frac_dst -! -! !ARGUMENTS: - implicit none - type(gridmap_type) , intent(in) :: gridmap ! gridmap data - integer, intent(in) :: mask_src(:) - real(r8), intent(out) :: frac_dst(:) -! -! !REVISION HISTORY: -! Created by Sam Levis -! -! !LOCAL VARIABLES: - integer :: n,ns,ni,no - real(r8):: wt - character(*),parameter :: subName = '(gridmap_calc_frac_dst) ' -!EOP -!------------------------------------------------------------------------------ - call gridmap_checkifset( gridmap, subname ) - frac_dst(:) = 0._r8 - - do n = 1,gridmap%ns - ni = gridmap%src_indx(n) - no = gridmap%dst_indx(n) - wt = gridmap%wovr(n) - if (mask_src(ni) > 0) then - frac_dst(no) = frac_dst(no) + wt*mask_src(ni) - end if - end do - - end subroutine gridmap_calc_frac_dst - -!========================================================================== - -!------------------------------------------------------------------------------ -!BOP -! -! !IROUTINE: gridmap_areaave_no_srcmask -! -! !INTERFACE: - subroutine gridmap_areaave_no_srcmask (gridmap, src_array, dst_array, nodata) -! -! !DESCRIPTION: -! This subroutine should NOT be used in general. We have kept it to support the -! rare raw data files for which we have masking on the mapping file and, -! therefore, we do not explicitly pass the src_mask as an argument. In general, -! users are advised to use subroutine gridmap_areaave_srcmask. -! -! Perform simple area average without explicitly passing a src mask. The src -! mask may be implicit in gridmap%wovr. -! -! !ARGUMENTS: - implicit none - type(gridmap_type) , intent(in) :: gridmap ! gridmap data - real(r8), intent(in) :: src_array(:) - real(r8), intent(out):: dst_array(:) - real(r8), intent(in) :: nodata ! value to apply where there are no input data -! -! !REVISION HISTORY: -! Created by Mariana Vertenstein -! -! !LOCAL VARIABLES: - integer :: n,ns,ni,no - real(r8):: wt,frac - real(r8), allocatable :: sum_weights(:) ! sum of weights on the output grid - character(*),parameter :: subName = '(gridmap_areaave_no_srcmask) ' -!EOP -!------------------------------------------------------------------------------ - call gridmap_checkifset( gridmap, subname ) - allocate(sum_weights(size(dst_array))) - sum_weights = 0._r8 - dst_array = 0._r8 - - do n = 1,gridmap%ns - ni = gridmap%src_indx(n) - no = gridmap%dst_indx(n) - wt = gridmap%wovr(n) - frac = gridmap%frac_dst(no) - if (frac > 0.) then - dst_array(no) = dst_array(no) + wt * src_array(ni)/frac - sum_weights(no) = sum_weights(no) + wt - end if - end do - - where (sum_weights == 0._r8) - dst_array = nodata - end where - - deallocate(sum_weights) - - end subroutine gridmap_areaave_no_srcmask - -end module mkgridmapMod - - diff --git a/tools/mksurfdata_map/src/mkharvestMod.F90 b/tools/mksurfdata_map/src/mkharvestMod.F90 deleted file mode 100644 index 0dc107729b..0000000000 --- a/tools/mksurfdata_map/src/mkharvestMod.F90 +++ /dev/null @@ -1,1104 +0,0 @@ -module mkharvestMod -!----------------------------------------------------------------------- -!BOP -! -! !MODULE: mkharvest -! -! !DESCRIPTION: -! Make harvest and grazing data to add to the dynamic PFT file. -! -! !REVISION HISTORY: -! Author: Erik Kluzek -! -!----------------------------------------------------------------------- -! !USES: - use shr_kind_mod , only : r8 => shr_kind_r8, CL => shr_kind_CL - use shr_sys_mod , only : shr_sys_flush - use mkdomainMod , only : domain_checksame - - implicit none - - private - -! !PUBLIC DATA MEMBERS: - - public :: harvestDataType - integer, private, parameter :: numharv = 9 ! number of harvest and grazing fields - - type :: harvestDataType - private - real(r8), pointer :: data1D(:,:) ! Input 1D data - real(r8), pointer :: data2DCFT(:,:,:) ! Input 2D data with CFT's - real(r8), pointer :: data2DPFT(:,:,:) ! Input 2D data with PFT's - real(r8), pointer :: OutData1D(:,:) ! Output 1D data - real(r8), pointer :: OutData2DCFT(:,:,:) ! Output 2D data with CFT's - real(r8), pointer :: OutData2DPFT(:,:,:) ! Output 2D data with natural PFT's - integer :: dims2nd(numharv) ! 2nd dimension size - integer :: CFTdimsize ! Size of CFT dimension - integer :: PFTdimsize ! Size of PFT dimension - integer :: indices1D(numharv) ! Field indices for CFT variables - integer :: indicesCFT(numharv) ! Field indices for CFT variables - integer :: indicesPFT(numharv) ! Field indices for PFT variables - contains - procedure :: init ! Initialization - procedure :: get1DFieldPtr ! Get a pointer to a 1D field - procedure :: get2DFieldPtr ! Get a pointer to a 2D field - procedure :: getFieldsIdx ! Get field indexes to 1D and 2D fields - procedure :: getFieldsDim ! Get dimension names for this field - procedure :: isField1D ! Return true if field is a 1D field - procedure :: isField2D ! Return true if field is a 2D field - procedure :: num1DFields ! Return the number of 1D fields - procedure :: num2DFields ! Return the number of 2D fields - procedure :: clean ! Clean and deallocate everything - end type harvestDataType - -! !PUBLIC MEMBER FUNCTIONS: - public mkharvest_init ! Initialization - public mkharvest ! Calculate the harvest values on output grid - public mkharvest_fieldname ! Field name for harvest fields on landuse.timeseries - public mkharvest_longname ! Long name - public mkharvest_units ! units - public mkharvest_numtypes ! Number of harvest types - public mkharvest_parse_oride ! Parse the over-ride string - -! !PRIVATE MEMBER FUNCTIONS: (but public because unit test uses them) - public mkharvest_fieldInBounds ! Check that field index is within bounds - -! !PRIVATE DATA MEMBERS: - - integer, parameter :: harlen = 25 ! length of strings for harvest fieldnames - character(len=harlen), parameter :: harvest_fieldnames(numharv) = (/ & - 'HARVEST_VH1 ', & - 'HARVEST_VH2 ', & - 'HARVEST_SH1 ', & - 'HARVEST_SH2 ', & - 'HARVEST_SH3 ', & - 'GRAZING ', & - 'FERTNITRO_CFT ', & - 'UNREPRESENTED_PFT_LULCC', & - 'UNREPRESENTED_CFT_LULCC' & - /) - character(len=harlen), parameter :: harvest_const_fieldnames(numharv) = (/ & - 'CONST_HARVEST_VH1 ', & - 'CONST_HARVEST_VH2 ', & - 'CONST_HARVEST_SH1 ', & - 'CONST_HARVEST_SH2 ', & - 'CONST_HARVEST_SH3 ', & - 'CONST_GRAZING ', & - 'CONST_FERTNITRO_CFT ', & - 'UNREPRESENTED_PFT_LULCC', & - 'UNREPRESENTED_CFT_LULCC' & - /) - character(len=CL), parameter :: string_undef = 'UNSET' - real(r8), parameter :: real_undef = -999.99 - character(len=CL), save :: harvest_longnames(numharv) = string_undef - character(len=CL), save :: harvest_units(numharv) = string_undef - real(r8), pointer :: oride_harv(:) ! array that can override harvesting - logical , save :: initialized = .false. - -!EOP -!----------------------------------------------------------------------- -contains -!----------------------------------------------------------------------- - -!----------------------------------------------------------------------- - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: init -! -! !INTERFACE: - subroutine init( this, dims2nd, ns_i, ns_o, init_value ) -! -! !DESCRIPTION: -! Initialization of the harvestData object -! -! !USES: - implicit none -! -! !ARGUMENTS: - class(harvestDataType), intent(INOUT) :: this ! harvestData object - integer, intent(IN) :: dims2nd(:) ! 2nd Dimension sizes - integer, intent(IN) :: ns_i ! Input dimension size - integer, intent(IN) :: ns_o ! Output dimension size - real(r8), intent(IN) :: init_value ! Initial value -! -! !REVISION HISTORY: -! Author: Erik Kluzek -! -! !LOCAL VARIABLES: - character(len=*), parameter :: subname = 'harvestData::init' - integer :: num2nd ! number of non 1D variables - integer :: numCFT, numPFT ! number of CFT and PFT variables respectively - integer :: num1D ! number of 1D variables - integer :: n ! index -!EOP -!----------------------------------------------------------------------- - if ( size(dims2nd) /= numharv )then - write(*,*) subname//':ERROR:: dims2nd given to init is not the right size' - call abort() - end if - this%CFTdimsize = 64 - this%PFTdimsize = 15 - this%dims2nd = dims2nd - num2nd = 0 - numCFT = 0 - numPFT = 0 - num1D = 0 - this%indices1D = -1 - this%indicesPFT = -1 - this%indicesCFT = -1 - do n = 1, numharv - if ( dims2nd(n) == 0 )then - num1D = num1D + 1 - this%indices1D(n) = num1D - else - num2nd = num2nd + 1 - if ( dims2nd(n) == this%CFTdimsize )then - numCFT = numCFT + 1 - this%indicesCFT(n) = numCFT - else if ( dims2nd(n) == this%PFTdimsize )then - numPFT = numPFT + 1 - this%indicesPFT(n) = numPFT - else - write(*,*) 'ERROR:: dims2nd is not the right size (should be 0, 15, or 64) = ', dims2nd(n) - call abort() - end if - end if - end do - - allocate( this%data1D(ns_i,num1D) ) - allocate( this%OutData1D(ns_o,num1D) ) - - this%OutData1D(:,:) = init_value - - if ( num2nd > 0 ) then - allocate( this%data2DCFT (ns_i,this%CFTdimsize,numCFT) ) - allocate( this%OutData2DCFT(ns_o,this%CFTdimsize,numCFT) ) - - this%OutData2DCFT(:,:,:) = init_value - - allocate( this%data2DPFT (ns_i,this%PFTdimsize,numPFT) ) - allocate( this%OutData2DPFT(ns_o,this%PFTdimsize,numPFT) ) - - this%OutData2DPFT(:,:,:) = init_value - end if - - end subroutine init - -!----------------------------------------------------------------------- - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: get1DFieldPtr -! -! !INTERFACE: - function get1DFieldPtr( this, nfield, output ) result(ptr1D) -! -! !DESCRIPTION: -! Returns 2D pointer to field data for this index -! -! !USES: - implicit none -! -! !ARGUMENTS: - class(harvestDataType), intent(IN) :: this ! harvestData object - integer, intent(in) :: nfield ! field index - real(r8), pointer :: ptr1D(:) ! Pointer to 1D data - logical, optional, intent(in) :: output ! Flag if this is the output pointer or not (input) -! -! !REVISION HISTORY: -! Author: Erik Kluzek -! -! !LOCAL VARIABLES: - character(len=*), parameter :: subname = 'harvestData::get1DFieldPtr' - logical :: loutput ! Local output flag -!EOP -!----------------------------------------------------------------------- - loutput = .false. - if ( present(output) ) loutput = output - if ( mkharvest_fieldInBounds( nfield ) .and. this%isField1D(nfield) )then - if ( .not. loutput ) then - ptr1D => this%data1D(:,this%indices1D(nfield)) - else - ptr1D => this%OutData1D(:,this%indices1D(nfield)) - end if - else - call abort() - end if - end function get1DFieldPtr - -!----------------------------------------------------------------------- - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: get2DFieldPtr -! -! !INTERFACE: - function get2DFieldPtr( this, nfield, output ) result(ptr2D) -! -! !DESCRIPTION: -! Returns 2D pointer to field data for this index -! -! !USES: - implicit none -! -! !ARGUMENTS: - class(harvestDataType), intent(IN) :: this ! harvestData object - integer, intent(in) :: nfield ! field index - real(r8), pointer :: ptr2D(:,:) ! Pointer to 2D data - logical, optional, intent(in) :: output ! Flag if this is the output pointer or not (input) -! -! !REVISION HISTORY: -! Author: Erik Kluzek -! -! !LOCAL VARIABLES: - character(len=*), parameter :: subname = 'harvestData::get2DFieldPtr' - logical :: loutput ! Local output flag -!EOP -!----------------------------------------------------------------------- - loutput = .false. - if ( present(output) ) loutput = output - if ( mkharvest_fieldInBounds( nfield ) .and. this%isField2D(nfield) )then - if ( .not. loutput ) then - if ( this%dims2nd(nfield) == this%CFTdimsize )then - ptr2D => this%data2DCFT(:,:,this%indicesCFT(nfield)) - else - ptr2D => this%data2DPFT(:,:,this%indicesPFT(nfield)) - end if - else - if ( this%dims2nd(nfield) == this%CFTdimsize )then - ptr2D => this%OutData2DCFT(:,:,this%indicesCFT(nfield)) - else - ptr2D => this%OutData2DPFT(:,:,this%indicesPFT(nfield)) - end if - end if - else - call abort() - end if - end function get2DFieldPtr - -!----------------------------------------------------------------------- - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: getFieldsIdx -! -! !INTERFACE: - subroutine getFieldsIdx( this, indices1D, indices2D ) -! -! !DESCRIPTION: -! Returns list of 1D and 2D fields indices -! -! !USES: - implicit none -! -! !ARGUMENTS: - class(harvestDataType), intent(IN) :: this ! harvestData object - integer, allocatable :: indices1D(:) ! List of 1D indices - integer, allocatable :: indices2D(:) ! List of 2D indices -! -! !REVISION HISTORY: -! Author: Erik Kluzek -! -! !LOCAL VARIABLES: - character(len=*), parameter :: subname = 'harvestData::getFieldsIdx' - integer :: ifld, n1, n2 ! field index and field index -!EOP -!----------------------------------------------------------------------- - allocate( indices1D(max(1,this%num1DFields()) ) ) - allocate( indices2D(max(1,this%num2DFields()) ) ) - indices1D = -1 - indices2D = -1 - n1 = 0 - n2 = 0 - do ifld = 1, mkharvest_numtypes() - if ( this%isField1D(ifld) )then - n1 = n1 + 1 - indices1D(n1) = ifld - else if ( this%isField2D(ifld) )then - n2 = n2 + 1 - indices2D(n2) = ifld - end if - end do - end subroutine getFieldsIdx - -!----------------------------------------------------------------------- - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: getFieldsDim -! -! !INTERFACE: - function getFieldsDim( this, nfield ) result(dimname) -! -! !DESCRIPTION: -! Returns list of 1D and 2D fields indices -! -! !USES: - implicit none -! -! !ARGUMENTS: - class(harvestDataType), intent(IN) :: this ! harvestData object - integer, intent(in) :: nfield ! field index - character(len=10) :: dimname ! Dimension names -! -! !REVISION HISTORY: -! Author: Erik Kluzek -! -! !LOCAL VARIABLES: - character(len=*), parameter :: subname = 'harvestData::getFieldsDim' -!EOP -!----------------------------------------------------------------------- - if ( this%dims2nd(nfield) == this%CFTdimsize )then - dimname = "cft" - else if ( this%dims2nd(nfield) == this%PFTdimsize )then - dimname = "natpft" - else - dimname = "none" - end if - end function getFieldsDim - -!----------------------------------------------------------------------- - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: isField1D -! -! !INTERFACE: - logical function isField1D( this, nfield ) -! -! !DESCRIPTION: -! Returns true if this field index is a 1D field -! -! !USES: - implicit none -! -! !ARGUMENTS: - class(harvestDataType), intent(IN) :: this ! harvestData object - integer, intent(in) :: nfield ! field index -! -! !REVISION HISTORY: -! Author: Erik Kluzek -! -! !LOCAL VARIABLES: - character(len=*), parameter :: subname = 'harvestData::isField1D' -!EOP -!----------------------------------------------------------------------- - isField1D = .false. - if ( mkharvest_fieldInBounds( nfield ) )then - if ( this%dims2nd(nfield) == 0 ) isField1D = .true. - else - call abort() - end if - end function isField1D - -!----------------------------------------------------------------------- - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: isField2D -! -! !INTERFACE: - logical function isField2D( this, nfield ) -! -! !DESCRIPTION: -! Returns true if this field index is a 2D field -! -! !USES: - implicit none -! -! !ARGUMENTS: - class(harvestDataType), intent(IN) :: this ! harvestData object - integer, intent(in) :: nfield ! field index -! -! !REVISION HISTORY: -! Author: Erik Kluzek -! -! !LOCAL VARIABLES: - character(len=*), parameter :: subname = 'harvestData::isField2D' -!EOP -!----------------------------------------------------------------------- - isField2D = .false. - if ( mkharvest_fieldInBounds( nfield ) )then - if ( this%dims2nd(nfield) /= 0 ) isField2D = .true. - else - call abort() - end if - end function isField2D - -!----------------------------------------------------------------------- - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: num1DFields -! -! !INTERFACE: - integer function num1DFields( this ) -! -! !DESCRIPTION: -! Returns the number of 1D fields -! -! !USES: - implicit none -! -! !ARGUMENTS: - class(harvestDataType), intent(IN) :: this ! harvestData object -! -! !REVISION HISTORY: -! Author: Erik Kluzek -! -! !LOCAL VARIABLES: - character(len=*), parameter :: subname = 'harvestData::num1DFields' -!EOP -!----------------------------------------------------------------------- - num1DFields = count( this%dims2nd == 0) - end function num1DFields - -!----------------------------------------------------------------------- - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: num2DFields -! -! !INTERFACE: - integer function num2DFields( this ) -! -! !DESCRIPTION: -! Returns the number of 2D fields -! -! !USES: - implicit none -! -! !ARGUMENTS: - class(harvestDataType), intent(IN) :: this ! harvestData object -! -! !REVISION HISTORY: -! Author: Erik Kluzek -! -! !LOCAL VARIABLES: - character(len=*), parameter :: subname = 'harvestData::num2DFields' -!EOP -!----------------------------------------------------------------------- - num2DFields = count( this%dims2nd /= 0) - end function num2DFields - -!----------------------------------------------------------------------- - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: mkharvest_init -! -! !INTERFACE: - subroutine mkharvest_init( ns_o, init_val, harvdata, fharvest, constant ) -! -! !DESCRIPTION: -! Initialization of mkharvest module. -! -! !USES: - use mkncdio - implicit none -! -! !ARGUMENTS: - integer , intent(in) :: ns_o ! clm output grid resolution - real(r8) , intent(in) :: init_val ! initial value to set to - type(harvestDataType), intent(INOUT) :: harvdata ! Harvest data - character(len=*) , intent(in) :: fharvest ! input harvest dataset file name - logical, intent(in), optional :: constant ! Flag if variables are CONST_ version for surface dataset - ! rather than landuse.timeseries -! -! !REVISION HISTORY: -! Author: Erik Kluzek -! -! -! !LOCAL VARIABLES: - character(len=*), parameter :: subname = 'mkharvest_init' - character(len=CL) :: lunits ! local units read in - integer :: ncid,varid ! input netCDF id's - integer :: ifld ! indices - integer :: ret ! return code - logical :: lconstant ! local version of constant flag - logical :: varexists ! If variable exists on file - integer :: dim_lengths(3) ! Dimension lengths on file - integer :: dims2nd(numharv) ! Dimension lengths of 3rd dimension for each variable on file - integer :: ndims ! Number of dimensions on file - integer :: ns_i ! clm input grid resolution (nlat*nlon) -!EOP -!----------------------------------------------------------------------- - lconstant = .false. - if ( present(constant) ) lconstant = constant - - initialized = .true. - call check_ret(nf_open(fharvest, 0, ncid), subname) - dims2nd(:) = 0 - ns_i = 0 - do ifld = 1, numharv - call check_ret(nf_inq_varid ( ncid, mkharvest_fieldname(ifld, constant=lconstant), varid), subname, varexists=varexists) - if ( .not. varexists )then - write(*,*) "SKIP: "//mkharvest_fieldname(ifld, constant=lconstant) - harvest_longnames(ifld) = trim(mkharvest_fieldname(ifld, constant=lconstant)) // " (zeroed out)" - harvest_units(ifld) = "not_read_in" - else - call check_ret(nf_get_att_text( ncid, varid, 'long_name', harvest_longnames(ifld)), subname ) - ret = nf_get_att_text( ncid, varid, 'units', harvest_units(ifld)) - if ( ret == nf_enotatt )then - harvest_units(ifld) = "unitless" - else if ( ret == nf_noerr )then - else - write(*,*) 'ERROR:: bad return code from NetCDF get attribute= '// nf_strerror(ret) - call abort() - end if - call get_dim_lengths(ncid, mkharvest_fieldname(ifld, constant=lconstant), ndims, dim_lengths) - if ( ns_i == 0 )then - ns_i = dim_lengths(1)*dim_lengths(2) - else if ( ns_i /= dim_lengths(1)*dim_lengths(2) )then - write(*,*) 'ERROR:: bad dimension sizes for variable = ', mkharvest_fieldname(ifld, constant=lconstant) - call abort() - end if - if ( ndims == 2 )then - dims2nd(ifld) = 0 - else if ( ndims == 3 )then - dims2nd(ifld) = dim_lengths(3) - else - write(*,*) 'ERROR:: bad dimensionality for variable = ', mkharvest_fieldname(ifld, constant=lconstant) - call abort() - end if - - end if - end do - call harvdata%init( dims2nd, ns_i, ns_o, init_val ) - - call check_ret(nf_close(ncid), subname) - - allocate( oride_harv(numharv) ) - oride_harv(:) = real_undef - - end subroutine mkharvest_init - -!----------------------------------------------------------------------- - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: mkharvest_fieldInBounds -! -! !INTERFACE: - logical function mkharvest_fieldInBounds( nfield ) -! -! !DESCRIPTION: -! Return true if field index is in bounds and initialization done -! -! !USES: - implicit none -! -! !ARGUMENTS: - integer, intent(in) :: nfield ! field index -! -! !REVISION HISTORY: -! Author: Erik Kluzek -! -! !LOCAL VARIABLES: - character(len=*), parameter :: subname = 'mkharvest_fieldInBounds' -!EOP -!----------------------------------------------------------------------- - if ( nfield < 1 )then - write(6,*) subname, ' ERROR nfield < 1' - mkharvest_fieldInBounds = .false. - else if ( nfield > numharv )then - write(6,*) subname, ' ERROR nfield > max fields' - mkharvest_fieldInBounds = .false. - else if ( .not. initialized ) then - write(6,*) subname, ' ERROR mkharvest NOT initialized yet!' - mkharvest_fieldInBounds = .false. - else - mkharvest_fieldInBounds = .true. - end if - - end function mkharvest_fieldInBounds - -!----------------------------------------------------------------------- - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: mkharvest_fieldname -! -! !INTERFACE: - character(len=harlen) function mkharvest_fieldname( nfield, constant ) -! -! !DESCRIPTION: -! Return harvest fieldname of input field number. -! -! !USES: - implicit none -! -! !ARGUMENTS: - integer, intent(in) :: nfield - logical, intent(in), optional :: constant -! -! !REVISION HISTORY: -! Author: Erik Kluzek -! -! !LOCAL VARIABLES: - character(len=*), parameter :: subname = 'mkharvest_fieldname' - logical :: lconstant ! local version of constant flag -!EOP -!----------------------------------------------------------------------- - lconstant = .false. - if ( present(constant) ) lconstant = constant - - if ( mkharvest_fieldInBounds( nfield ) )then - if ( .not. lconstant )then - mkharvest_fieldname = harvest_fieldnames(nfield) - else - mkharvest_fieldname = harvest_const_fieldnames(nfield) - end if - else - call abort() - end if - - end function mkharvest_fieldname - -!----------------------------------------------------------------------- - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: mkharvest_units -! -! !INTERFACE: - character(len=CL) function mkharvest_units( nfield ) -! -! !DESCRIPTION: -! Return units description of harvest fields -! -! !USES: - implicit none -! -! !ARGUMENTS: - integer, intent(in) :: nfield -! -! !REVISION HISTORY: -! Author: Erik Kluzek -! -! -! !LOCAL VARIABLES: - character(len=*), parameter :: subname = 'mkharvest_units' -!EOP -!----------------------------------------------------------------------- - - if ( mkharvest_fieldInBounds( nfield ) )then - mkharvest_units = harvest_units(nfield) - else - call abort() - end if - - end function mkharvest_units - -!----------------------------------------------------------------------- - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: mkharvest_longname -! -! !INTERFACE: - character(len=CL) function mkharvest_longname( nfield ) -! -! !DESCRIPTION: -! Return longname description of given input field number. -! -! !USES: - implicit none -! -! !ARGUMENTS: - integer, intent(in) :: nfield -! -! !REVISION HISTORY: -! Author: Erik Kluzek -! -! -! !LOCAL VARIABLES: - character(len=*), parameter :: subname = 'mkharvest_longname' -!EOP -!----------------------------------------------------------------------- - - if ( mkharvest_fieldInBounds( nfield ) )then - mkharvest_longname = harvest_longnames(nfield) - else - call abort() - end if - - end function mkharvest_longname - -!----------------------------------------------------------------------- - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: mkharvest_numtypes -! -! !INTERFACE: - integer function mkharvest_numtypes( ) -! -! !DESCRIPTION: -! Return number of different harvest field types. -! -! !USES: - implicit none -! -! !ARGUMENTS: - character(len=*), parameter :: subname = 'mkharvest_numtypes' -! -! !REVISION HISTORY: -! Author: Erik Kluzek -! -! -! !LOCAL VARIABLES: -!EOP -!----------------------------------------------------------------------- - mkharvest_numtypes = numharv - - end function mkharvest_numtypes - -!----------------------------------------------------------------------- - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: clean -! -! !INTERFACE: - subroutine clean( this ) -! -! !DESCRIPTION: -! Clean and deallocate the harvestData object -! -! !USES: - implicit none -! -! !ARGUMENTS: - class(harvestDataType), intent(INOUT) :: this ! harvestData object -! -! !REVISION HISTORY: -! Author: Erik Kluzek -! -! !LOCAL VARIABLES: - character(len=*), parameter :: subname = 'harvestData::clean' -!EOP -!----------------------------------------------------------------------- - this%CFTdimsize = -1 - this%PFTdimsize = -1 - - if ( associated(this%data1D) ) deallocate( this%data1D ) - if ( associated(this%Outdata1D) ) deallocate( this%OutData1D ) - - if ( associated(this%data2DCFT) ) deallocate( this%data2DCFT ) - if ( associated(this%OutData2DCFT)) deallocate( this%OutData2DCFT ) - if ( associated(this%data2DPFT ) ) deallocate( this%data2DPFT ) - if ( associated(this%OutData2DPFT)) deallocate( this%OutData2DPFT ) - this%data2DCFT => null() - this%OutData2DCFT => null() - this%data2DPFT => null() - this%OutData2DPFT => null() - - end subroutine clean - -!----------------------------------------------------------------------- - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: mkharvest -! -! !INTERFACE: -subroutine mkharvest(ldomain, mapfname, datfname, ndiag, harvdata) -! -! !DESCRIPTION: -! Make harvest data for the dynamic PFT dataset. -! This dataset consists of the normalized harvest or grazing fraction (0-1) of -! the model. -! -! !USES: - use mkdomainMod, only : domain_type, domain_clean, domain_read - use mkgridmapMod - use mkvarpar - use mkvarctl - use mkncdio -! -! !ARGUMENTS: - implicit none - type(domain_type) , intent(in) :: ldomain ! - character(len=*) , intent(in) :: mapfname ! input mapping file name - character(len=*) , intent(in) :: datfname ! input data file name - integer , intent(in) :: ndiag ! unit number for diag out - type(harvestDataType), intent(INOUT) :: harvdata ! Harvest data -! -! !CALLED FROM: -! subroutine mksrfdat in module mksrfdatMod -! -! !REVISION HISTORY: -! Author: Erik Kluzek -! -! -! !LOCAL VARIABLES: -!EOP - type(gridmap_type) :: tgridmap - type(domain_type) :: tdomain ! local domain - real(r8) :: gharv_o(numharv) ! output grid: global area harvesting - real(r8) :: garea_o ! output grid: global area - real(r8) :: gharv_i(numharv) ! input grid: global area harvesting - real(r8) :: garea_i ! input grid: global area - integer :: ifld ! indices - integer :: k,n,m,ni,no,ns_i,ns_o ! indices - integer :: ncid,varid ! input netCDF id's - logical :: varexists ! If variable exists or not - integer :: ier ! error status - integer, allocatable :: ind1D(:) ! Index of 1D harvest fields - integer, allocatable :: ind2D(:) ! Index of 2D harvest fields - real(r8), allocatable :: frac_dst(:) ! output fractions - real(r8), pointer :: data1D_i(:) ! 1D input data - real(r8), pointer :: data2D_i(:,:) ! 2D output data - real(r8), pointer :: data1D_o(:) ! 1D output data - real(r8), pointer :: data2D_o(:,:) ! 2D output data - - character(len=*), parameter :: unit = '10**6 km**2' ! Output units - real(r8), parameter :: fac = 1.e-06_r8 ! Output factor - real(r8), parameter :: rat = fac/100._r8 ! Output factor divided by 100% - character(len=*), parameter :: subname = 'mkharvest' -!----------------------------------------------------------------------- - - write (6,*) 'Attempting to make harvest fields .....' - call shr_sys_flush(6) - - ! ----------------------------------------------------------------- - ! Normally read in the harvesting file, and then regrid to output grid - ! ----------------------------------------------------------------- - call harvdata%getFieldsIdx( ind1D, ind2D ) - - if ( all(oride_harv == real_undef ) )then - - ! ----------------------------------------------------------------- - ! Read input harvesting file - ! ----------------------------------------------------------------- - - ! Obtain input grid info, read HARVEST_VH1, HARVEST_VH2, ... GRAZING etc. - - call domain_read(tdomain,datfname) - ns_i = tdomain%ns - ns_o = ldomain%ns - allocate(frac_dst(ns_o), stat=ier) - if (ier /= 0) call abort() - - write (6,*) 'Open harvest file: ', trim(datfname) - call check_ret(nf_open(datfname, 0, ncid), subname) - do k = 1, harvdata%num1Dfields() - ifld = ind1D(k) - call check_ret( nf_inq_varid(ncid, mkharvest_fieldname(ifld), varid), subname, varexists=varexists ) - data1D_i => harvdata%get1DFieldPtr( ifld ) - if ( .not. varexists )then - write(*,*) "SKIP: "//mkharvest_fieldname(ifld) - data1D_i(:) = 0.0_r8 - else - call check_ret(nf_get_var_double (ncid, varid, data1D_i), subname) - end if - end do - do k = 1, harvdata%num2Dfields() - ifld = ind2D(k) - call check_ret( nf_inq_varid(ncid, mkharvest_fieldname(ifld), varid), subname, varexists=varexists ) - data2D_i => harvdata%get2DFieldPtr( ifld ) - if ( .not. varexists )then - write(*,*) "SKIP: "//mkharvest_fieldname(ifld) - data2D_i(:,:) = 0.0_r8 - else - call check_ret(nf_get_var_double (ncid, varid, data2D_i), subname) - end if - end do - call check_ret(nf_close(ncid), subname) - - ! Area-average normalized harvest on input grid [data*_i] to output grid [data*_o] - - call gridmap_mapread(tgridmap, mapfname ) - - ! Error checks for domain and map consistencies - - call domain_checksame( tdomain, ldomain, tgridmap ) - - ! Obtain frac_dst - call gridmap_calc_frac_dst(tgridmap, tdomain%mask, frac_dst) - - ! Determine data* on output grid - - do k = 1, harvdata%num1Dfields() - ifld = ind1D(k) - data1D_i => harvdata%get1DFieldPtr( ifld ) - data1D_o => harvdata%get1DFieldPtr( ifld, output=.true. ) - call gridmap_areaave_srcmask(tgridmap, data1D_i, data1D_o, nodata=0._r8, mask_src=tdomain%mask, frac_dst=frac_dst) - end do - do k = 1, harvdata%num2Dfields() - ifld = ind2D(k) - data2D_i => harvdata%get2DFieldPtr( ifld ) - data2D_o => harvdata%get2DFieldPtr( ifld, output=.true. ) - do m = lbound(data2D_i(:,:),dim=2), ubound(data2D_i(:,:),dim=2) - call gridmap_areaave_srcmask(tgridmap, data2D_i(:,m), data2D_o(:,m), nodata=0._r8, mask_src=tdomain%mask, frac_dst=frac_dst) - end do - end do - - ! ----------------------------------------------------------------- - ! Error check - ! Compare global areas on input and output grids - ! ----------------------------------------------------------------- - - gharv_i(:) = 0. - garea_i = 0. - do ni = 1, ns_i - garea_i = garea_i + tgridmap%area_src(ni)*re**2 - do k = 1, harvdata%num1Dfields() - m = ind1D(k) - data1D_i => harvdata%get1DFieldPtr( m ) - gharv_i(m) = gharv_i(m) + data1D_i(ni)*tgridmap%area_src(ni)* & - tdomain%mask(ni)*re**2 - end do - end do - - gharv_o(:) = 0. - garea_o = 0. - do no = 1,ns_o - garea_o = garea_o + tgridmap%area_dst(no)*re**2 - do k = 1, harvdata%num1Dfields() - m = ind1D(k) - data1D_o => harvdata%get1DFieldPtr( m, output=.true. ) - gharv_o(m) = gharv_o(m) + data1D_o(no)*tgridmap%area_dst(no)* & - frac_dst(no)*re**2 - end do - end do - - ! Write out to diagnostic output file - ! - - write (ndiag,*) - write (ndiag,'(1x,70a1)') ('=',k=1,70) - write (ndiag,*) 'Harvesting Output' - write (ndiag,'(1x,70a1)') ('=',k=1,70) - - write (ndiag,*) - write (ndiag,'(1x,70a1)') ('.',k=1,70) - write (ndiag,1001) unit, unit -1001 format (1x,'harvest type ',20x,' input grid area',' output grid area',/ & - 1x,33x,' ',A,' ',A) - write (ndiag,'(1x,70a1)') ('.',k=1,70) - write (ndiag,*) - do k = 1, harvdata%num1Dfields() - m = ind1D(k) - write (ndiag,1002) mkharvest_fieldname(m), gharv_i(m)*rat,gharv_o(m)*rat - end do -1002 format (1x,a35,f16.3,f17.3) - - ! Deallocate dynamic memory - - call domain_clean(tdomain) - call gridmap_clean(tgridmap) - - else - - ! ----------------------------------------------------------------- - ! Otherwise override the harvesting with the input harvest values - ! ----------------------------------------------------------------- - - if ( any(oride_harv == real_undef ) )then - write(6,*) subname, ' error some override harvesting fields set ', & - 'and others are not = ', oride_harv - call abort() - end if - do k = 1, harvdata%num1Dfields() - m = ind1D(k) - if ( oride_harv(m) < 0.0_r8 .or. oride_harv(m) > 100.0_r8 )then - write(6,*) subname, ' error override harvesting field out of range', & - oride_harv(m), ' field = ', mkharvest_fieldname(m) - call abort() - end if - end do - do no = 1,ns_o - do k = 1, harvdata%num1Dfields() - m = ind1D(k) - data1D_o => harvdata%get1DFieldPtr( m, output=.true. ) - data1D_o(no) = oride_harv(m) - end do - end do - - end if - - deallocate( ind1D, ind2D ) - write (6,*) 'Successfully made harvest and grazing' - write (6,*) - -end subroutine mkharvest - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: mkharvest_parse_oride -! -! !INTERFACE: -subroutine mkharvest_parse_oride( string ) -! -! !DESCRIPTION: -! Parse the string with harvest and grazing information on it, to override -! the file with this information rather than reading from a file. -! -! !USES: - use shr_string_mod, only: shr_string_betweenTags -! !ARGUMENTS: - character(len=256), intent(IN) :: string ! String to parse with harvest and grazing data -! -! !CALLED FROM: -! subroutine mksrfdat in module mksrfdatMod -! -! !REVISION HISTORY: -! Author: Erik Kluzek -! -! -! !LOCAL VARIABLES: -!EOP - integer :: rc ! error return code - character(len=256) :: substring ! substring between tags - character(len=*), parameter :: harv_start = "" - character(len=*), parameter :: harv_end = "" - character(len=*), parameter :: graz_start = "" - character(len=*), parameter :: graz_end = "" - character(len=*), parameter :: subname = 'mkharvest_parse_oride' -!----------------------------------------------------------------------- - call shr_string_betweenTags( string, harv_start, harv_end, substring, rc ) - if ( rc /= 0 )then - write(6,*) subname//'Trouble finding harvest start end tags' - call abort() - end if - read(substring,*) oride_harv(1:numharv-1) - call shr_string_betweenTags( string, graz_start, graz_end, substring, rc ) - if ( rc /= 0 )then - write(6,*) subname//'Trouble finding grazing start end tags' - call abort() - end if - read(substring,*) oride_harv(numharv) - if ( harvest_fieldnames(numharv) /= 'GRAZING' )then - write(6,*) subname, ' grazing is NOT last field as was expected' - call abort() - end if - -!----------------------------------------------------------------------- - -end subroutine mkharvest_parse_oride - -!----------------------------------------------------------------------- - -end module mkharvestMod diff --git a/tools/mksurfdata_map/src/mkindexmapMod.F90 b/tools/mksurfdata_map/src/mkindexmapMod.F90 deleted file mode 100644 index 5f8e74af2b..0000000000 --- a/tools/mksurfdata_map/src/mkindexmapMod.F90 +++ /dev/null @@ -1,697 +0,0 @@ -module mkindexmapMod -!----------------------------------------------------------------------- -!BOP -! -! !MODULE: mkindexmapMod -! -! !DESCRIPTION: -! Module containing subroutines for making maps of index data. -! -! This includes a routine for making a map using the dominant type among the input grid -! cells making up a given output cell, as well as routines for using an index map as -! indices into a lookup table, to essentially paint-by-number some other field, and some -! other related routines -! -! WJS (2-1-12): There is a lookup_2d subroutine, but not a lookup_1d (or any other -! dimensionality). That is simply because I needed lookup_2d, but have not yet needed a -! routine of other dimensionalities. In the future, it would probably be helpful to at -! least have lookup_1d and lookup_1d_netcdf. If this is done, see my notes under the -! lookup_2d_netcdf routine for some thoughts on avoiding duplication. -! -! -! !USES: - use shr_kind_mod, only : r8 => shr_kind_r8 - use mkncdio, only : nf_max_name - use mkgridmapMod, only : gridmap_type - - implicit none - private - -! !PUBLIC TYPES: -! - ! dim_slice_type: stores information about dimensions that we use for slicing a multi- - ! dimensional variable - type dim_slice_type - character(len=nf_max_name) :: name ! name of this dimension - integer :: val ! index to use for the slice - end type dim_slice_type - public :: dim_slice_type -! -! !PUBLIC MEMBER FUNCTIONS: - public :: get_dominant_indices ! make output map based on dominant type in each grid cell - public :: get_max_indices ! make output map based on maximum type in each grid cell - public :: lookup_2d ! create map based on a 2-d lookup table - public :: lookup_2d_netcdf ! wrapper to lookup_2d; first read table from netcdf file - public :: which_max ! get index of the maximum value in an array -! -! -! !REVISION HISTORY: -! Author: Bill Sacks -! -!EOP -!------------------------------------------------------------------------------ -contains - -!------------------------------------------------------------------------------ -!BOP -! -! !IROUTINE: get_dominant_indices -! -! !INTERFACE: -subroutine get_dominant_indices(gridmap, src_array, dst_array, minval, maxval, nodata, filter, mask_src) -! -! !DESCRIPTION: -! Fills an output array on the destination grid (dst_array) whose values are equal to the -! (weighted) dominant value in the source grid cells overlapping a given destination grid -! cell -! -! Ignores all values in src_array that are less than minval or greater than maxval (treats -! those values the same as if they had wt=0). (Note: for memory-use efficiency, it is -! best if the indices are designed such that most values between minval and maxval are -! actually used, since an array is allocated of size (maxval - minval + 1)*gridmap%nb.) -! -! The filter argument can be used to exclude certain overlaps -- if provided, we only -! consider overlaps where filter is .true. If not provided, filter is treated as being -! .true. everywhere. -! -! Output grid cells with no contributing valid source points are given the nodata value -! -! !ARGUMENTS: - implicit none - type(gridmap_type), intent(in) :: gridmap ! provides mapping from src -> dst - integer , intent(in) :: src_array(:) ! input values; length gridmap%na - integer , intent(out):: dst_array(:) ! output values; length gridmap%nb - integer , intent(in) :: minval ! minimum valid value in src_array - integer , intent(in) :: maxval ! maximum valid value in src_array - integer , intent(in) :: nodata ! value to assign to dst_array where there are no valid source points - integer , intent(in) :: mask_src(:) - - logical, intent(in), optional :: filter(:) ! only consider overlaps where filter is .true.; length gridmap%ns -! -! !REVISION HISTORY: -! Author: Bill Sacks -! -! -! !LOCAL VARIABLES: -!EOP - logical, allocatable :: lfilter(:) ! local version of filter - logical, allocatable :: hasdata(:) ! true if an output cell has any valid data; - real(r8), allocatable :: weights(:,:) ! summed weight of each index value for each output cell - - integer :: n, ni, no - integer :: k - integer :: maxindex - real(r8) :: wt - real(r8) :: maxwt - - character(len=*), parameter :: subname = "get_dominant_indices" -!----------------------------------------------------------------------- - - ! Error-check inputs and initialize local variables - - if (size(src_array) /= gridmap%na .or. & - size(dst_array) /= gridmap%nb) then - write(6,*) subname//' ERROR: incorrect sizes of src_array or dst_array' - write(6,*) 'size(src_array) = ', size(src_array) - write(6,*) 'gridmap%na = ', gridmap%na - write(6,*) 'size(dst_array) = ', size(dst_array) - write(6,*) 'gridmap%nb = ', gridmap%nb - call abort() - end if - if (size(mask_src) /= size(src_array)) then - write(6,*) subname//' ERROR: incorrect size of mask_src' - write(6,*) 'size(mask_src) = ', size(mask_src) - write(6,*) 'size(src_array) = ', size(src_array) - call abort() - end if - - allocate(lfilter(gridmap%ns)) - - if (present(filter)) then - if (size(filter) /= gridmap%ns) then - write(6,*) subname//' ERROR: incorrect size of filter' - write(6,*) 'size(filter) = ', size(filter) - write(6,*) 'gridmap%ns = ', gridmap%ns - call abort() - end if - - lfilter(:) = filter(:) - else - lfilter(:) = .true. - end if - - allocate(hasdata(gridmap%nb)) - hasdata(:) = .false. - allocate(weights(minval:maxval, gridmap%nb)) - weights(minval:maxval,:) = 0. - - ! Determine weight of each index value for each output (destination) cell - - do n = 1, gridmap%ns - if (lfilter(n)) then - ni = gridmap%src_indx(n) - no = gridmap%dst_indx(n) - wt = gridmap%wovr(n) * mask_src(ni) - k = src_array(ni) - if (k >= minval .and. k <= maxval) then - ! Note: if we were doing something like weighted sums, I think we would - ! want to divide wt by gridmap%frac_dst(no), as is done in - ! gridmap_areaave_default. But since all we care about is the relative - ! values of weights for a given destination cell, this is unnecessary - weights(k,no) = weights(k,no) + wt - hasdata(no) = .true. - end if - end if - end do - - ! Determine output values - ! Note: if a given destination cell has no contributing source points (thus - ! hasdata(no) = false), or the max weight of any index overlapping this destination - ! cell is <= 0, then the output value there will be nodata. - ! (I don't think this latter condition -- weight <= 0 -- is possible, but we handle - ! it anyway) - - dst_array(:) = nodata - do no = 1, gridmap%nb - if (hasdata(no)) then - call which_max(weights(:,no), maxwt, maxindex, lbound=minval) - if (maxwt > 0.) then - dst_array(no) = maxindex - end if - end if - end do - - deallocate(lfilter, weights, hasdata) - -end subroutine get_dominant_indices -!------------------------------------------------------------------------------ - -!----------------------------------------------------------------------- -subroutine get_max_indices(gridmap, src_array, dst_array, nodata, mask_src) - ! - ! !DESCRIPTION: - ! Fills an output array on the destination grid (dst_array) whose values are equal to - ! the maximum value in the source grid cells overlapping a given destination grid cell. - ! - ! The frequency of occurrence of the source values is irrelevant. For example, if the - ! value 1 appears in 99% of source cells overlapping a given destination cell and the - ! value 2 appears in just 1%, we'll put 2 in the destination cell because it is the - ! maximum value. - ! - ! Output grid cells with no contributing valid source points are given the nodata value - ! - ! !ARGUMENTS: - type(gridmap_type) , intent(in) :: gridmap ! provides mapping from src -> dst - integer , intent(in) :: src_array(:) ! input values; length gridmap%na - integer , intent(out) :: dst_array(:) ! output values; length gridmap%nb - integer , intent(in) :: nodata ! value to assign to dst_array where there are no valid source points - integer , intent(in) :: mask_src(:) ! mask at the source resolution - ! - ! !LOCAL VARIABLES: - logical, allocatable :: hasdata(:) ! true if an output cell has any valid data; - integer :: n, ni, no - real(r8) :: wt - integer :: src_val - - character(len=*), parameter :: subname = 'get_max_indices' - !----------------------------------------------------------------------- - - ! Error-check inputs - - if (size(src_array) /= gridmap%na .or. & - size(dst_array) /= gridmap%nb) then - write(6,*) subname//' ERROR: incorrect sizes of src_array or dst_array' - write(6,*) 'size(src_array) = ', size(src_array) - write(6,*) 'gridmap%na = ', gridmap%na - write(6,*) 'size(dst_array) = ', size(dst_array) - write(6,*) 'gridmap%nb = ', gridmap%nb - call abort() - end if - if (size(mask_src) /= size(src_array)) then - write(6,*) subname//' ERROR: incorrect size of mask_src' - write(6,*) 'size(mask_src) = ', size(mask_src) - write(6,*) 'size(src_array) = ', size(src_array) - call abort() - end if - - ! Initialize local variables - allocate(hasdata(gridmap%nb)) - hasdata(:) = .false. - - do n = 1, gridmap%ns - ni = gridmap%src_indx(n) - wt = gridmap%wovr(n) * mask_src(ni) - if (wt > 0._r8) then - no = gridmap%dst_indx(n) - src_val = src_array(ni) - if (.not. hasdata(no)) then - hasdata(no) = .true. - dst_array(no) = src_val - else if (src_val > dst_array(no)) then - dst_array(no) = src_val - end if - end if - end do - - do no = 1, gridmap%nb - if (.not. hasdata(no)) then - dst_array(no) = nodata - end if - end do - -end subroutine get_max_indices - - -!------------------------------------------------------------------------------ -!BOP -! -! !IROUTINE: lookup_2d -! -! !INTERFACE: -subroutine lookup_2d(index1, index2, lookup_table, fill_val, data, ierr, & - nodata, valid_entries, invalid_okay) -! -! !DESCRIPTION: -! Creates a data array using a paint-by-number approach according to a lookup table -! -! This routine operates on a 2-d lookup table. There are therefore two index arrays -! (index1 and index2); these index arrays are on the same grid as the desired data array -! (thus, index1, index2 and data must all have the same length). Each output point, n, is -! then generally determined as: -! -! data(n) = lookup_table(index1(n), index2(n)) -! -! fill_val: value to put in data array where either: -! (a) index1 or index2 are equal to nodata (if nodata is given) -! Note that this condition does NOT result in ierr being set -! (b) valid_entries(index1(n), index2(n)) is false (if valid_entries is given) -! Note that this condition also results in ierr being set, unless invalid_okay is -! present and .true. -! (If valid_entries is not given, it is treated as being .true. everywhere) -! (c) index1 or index2 out of range -! Note that this condition also results in ierr being set -! -! ierr: error return code (if non-0, indicates first error encountered): -! 0: no error -! 1: attempt to assign values from the lookup table that are invalid according -! to valid_entries (note: this is not considered an error if invalid_okay is -! present and .true.) -! 2: attempt to access an out-of-range index in lookup table -! WJS (2-2-12): My main reason for using ierr rather than aborting in case of error -! is to facilitate unit testing -! -! !ARGUMENTS: - implicit none - integer , intent(in) :: index1(:) ! index into dim 1 of lookup_table - integer , intent(in) :: index2(:) ! index into dim 2 of lookup_table - real(r8), intent(in) :: lookup_table(:,:) - real(r8), intent(in) :: fill_val ! value to put in data where we don't have a valid value (see above for details) - real(r8), intent(out):: data(:) ! output arary - integer , intent(out):: ierr ! error return code (0 = no error) - - ! nodata flag in index1 and index2 (see above for details): - integer, intent(in), optional :: nodata - - ! which entries are considered valid (see above for details): - logical, intent(in), optional :: valid_entries(:,:) - - ! invalid_okay: if true, then assigning fill_val because valid_entries is false does - ! NOT raise an error flag (invalid_okay defaults to false, meaning an error is - ! raised in this case): - logical, intent(in), optional :: invalid_okay -! -! !REVISION HISTORY: -! Author: Bill Sacks -! -! -! !LOCAL VARIABLES: -!EOP - integer :: n - integer :: i1, i2 - integer :: data_size ! size of index1, index2 and data arrays - integer :: table_n1 ! size of dimension 1 of lookup table - integer :: table_n2 ! size of dimension 2 of lookup table - logical :: linvalid_okay ! local version of invalid_okay - logical, allocatable :: lvalid_entries(:,:) ! local version of valid_entries - - character(len=*), parameter :: subname = 'lookup_2d' -!----------------------------------------------------------------------- - - ierr = 0 - - ! Error-check array sizes - - data_size = size(data) - if (size(index1) /= data_size .or. size(index2) /= data_size) then - write(6,*) subname//' ERROR: data array sizes do not match' - write(6,*) 'size(data) = ', data_size - write(6,*) 'size(index1) = ', size(index1) - write(6,*) 'size(index2) = ', size(index2) - call abort() - end if - - table_n1 = size(lookup_table,1) - table_n2 = size(lookup_table,2) - if (present(valid_entries)) then - if (size(valid_entries,1) /= table_n1 .or. size(valid_entries,2) /= table_n2) then - write(6,*) subname//' ERROR: size of valid_entries does not match lookup_table' - write(6,*) 'size(lookup_table) = ', table_n1, table_n2 - write(6,*) 'size(valid_entries) = ', size(valid_entries,1), & - size(valid_entries,2) - call abort() - end if - end if - - ! Set local version of invalid_okay & valid_entries - - if (present(invalid_okay)) then - linvalid_okay = invalid_okay - else - linvalid_okay = .false. - end if - - allocate(lvalid_entries(table_n1, table_n2)) - if (present(valid_entries)) then - lvalid_entries(:,:) = valid_entries(:,:) - else - lvalid_entries(:,:) = .true. - end if - - ! Do the lookups - - do n = 1, data_size - i1 = index1(n) - i2 = index2(n) - - ! First handle special cases: - - ! index is nodata flag (this is NOT an error) - if (present(nodata)) then - if (i1 == nodata .or. i2 == nodata) then - data(n) = fill_val - cycle - end if - end if - - ! index out of range - if (i1 <= 0 .or. i1 > table_n1 .or. & - i2 <= 0 .or. i2 > table_n2) then - data(n) = fill_val - if (ierr == 0) ierr = 2 - cycle - end if - - ! lookup table entry is invalid - if (.not. lvalid_entries(i1, i2)) then - data(n) = fill_val - if (.not. linvalid_okay) then - if (ierr == 0) ierr = 1 - end if - cycle - end if - - ! Finally, the "normal" case, if none of the special cases were triggered: - data(n) = lookup_table(i1, i2) - end do - - deallocate(lvalid_entries) - -end subroutine lookup_2d -!------------------------------------------------------------------------------ - -!------------------------------------------------------------------------------ -!BOP -! -! !IROUTINE: lookup_2d_netcdf -! -! !INTERFACE: -subroutine lookup_2d_netcdf(ncid, tablename, lookup_has_invalid, & - dimname1, dimname2, n_extra_dims, & - index1, index2, fill_val, data, ierr, & - extra_dims, nodata, invalid_okay) -! -! !DESCRIPTION: -! Wrapper to lookup_2d that first reads the lookup table from a netcdf file -! -! If lookup_has_invalid is false, then we treat all lookup table entries as valid data -! (i.e., all valid_entries are true in the call to lookup_2d). If lookup_has_invalid is -! true, then we read the _FillValue attribute for the lookup table variable, and consider -! any table entry with value _FillValue to be an invalid entry, thus putting fill_val in -! these data locations (and raising an error flag unless invalid_okay is present and -! true). -! -! The dimension given by dimname1 -- with the associated indices given by index1 -- is the -! fastest-varying dimension in the lookup table. Dimension dimname2 (associated with -! index2) is the second-fastest-varying dimension. Similarly, extra_dims should be ordered -! from faster-varying to slowest-varying dimension. (The first dimension in extra_dims is -! the third-fastest-varying dimension in the lookup table.) -! -! n_extra_dims gives the number of extra dimensions (in addition to the first two) in the -! lookup table. We take a single 2-d slice of the lookup table, by using a single value of -! each of these other dimensions. If n_extra_dims > 0, then extra_dims must be present, -! with at least n_extra_dims entries. Each entry in extra_dims gives the name of a -! dimension and the dimension index to use for the slice. -! -! If size(extra_dims) > n_extra_dims, then we use the first n_extra_dims entries in -! extra_dims. If n_extra_dims = 0, then extra_dims is ignored. -! -! Note that we ignore any coordinate variables associated with the dimensions of the -! lookup table; we simply treat the lookup table indices as 1,2,3,... -! -! See the lookup_2d documentation for documentation of some other arguments -! -! WJS (2-1-12): Some thoughts on avoiding duplication if we eventually want similar -! routines, lookup_1d_netcdf, lookup_3d_netcdf, etc.: -! -! Much of the code in lookup_2d_netcdf could then be pulled out to a shared subroutine -! (e.g., much of the error-checking code). -! -! Or, maybe better: we could try to make a single lookup_netcdf subroutine that handles -! 1-d, 2-d and any other dimensionality. To do that, we would (1) make a generic interface -! (of which lookup_1d and lookup_2d would be implementations); (2) change the repeated -! arguments in lookup_2d_netcdf (*1 and *2) to arrays -- maybe using an array of a derived -! type containing these arguments; (3) if possible, initially read the lookup table into a -! 1-d array (if the netcdf call allows reading a n-d array into a 1-d array) (if netcdf -! doesn't allow this, then I think we could achieve the same thing by reading 1-d slices -! of the lookup table in a loop, building the full lookup table as a long 1-d array); (4) -! in the call to the generic 'lookup' function, reshape the 1-d lookup table -! appropriately. (Note: I think it would be challenging to combine lookup_1d and lookup_2d -! (etc.) into a single routine using a similar method.) -! -! !USES: - use mkncdio -! !ARGUMENTS: - implicit none - integer , intent(in) :: ncid ! ID of an open netcdf file - character(len=*), intent(in) :: tablename ! name of the lookup table variable - logical , intent(in) :: lookup_has_invalid ! should we use _FillValue? (see above) - character(len=*), intent(in) :: dimname1 ! name of the first (fastest-varying) dimension of the lookup table - character(len=*), intent(in) :: dimname2 ! name of the second dimension of the lookup table - integer , intent(in) :: n_extra_dims ! number of extra dimensions in the lookup table - ! The following arguments are passed directly to lookup_2d: - integer , intent(in) :: index1(:) ! index into dim 1 of lookup table - integer , intent(in) :: index2(:) ! index into dim 2 of lookup table - real(r8) , intent(in) :: fill_val ! value to put in data where we don't have a valid value - real(r8) , intent(out):: data(:) ! output array - integer , intent(out):: ierr ! error return code from the call to lookup_2d - - ! slice to use if lookup table variable has more than 2 dimensions: - type(dim_slice_type), intent(in), optional :: extra_dims(:) - - ! nodata flag in index1 and index2, passed directly to lookup_2d: - integer , intent(in), optional :: nodata - - ! flag for whether trying to use a lookup table value that is equal to the _FillValue - ! should raise an error flag - ! (irrelevant if lookup_has_invalid is .false.) - ! (passed directly to lookup_2d - see the documentation there for more details) - logical , intent(in), optional :: invalid_okay -! -! !REVISION HISTORY: -! Author: Bill Sacks -! -! -! !LOCAL VARIABLES: -!EOP - integer :: varid ! netcdf variable id of the lookup table - integer :: ndims ! total number of dimensions of lookup table - integer :: ndims_expected ! value we expect for ndims, for error checking - integer :: i - real(r8) :: table_fillval ! value of the _FillValue attribute for the lookup table - character(len=nf_max_name), allocatable :: dimnames(:) ! dimension names - integer , allocatable :: dimids(:) ! dimension ids - integer , allocatable :: dimlens(:) ! dimension lengths - integer , allocatable :: starts(:) ! starting indices for reading lookup table - integer , allocatable :: counts(:) ! dimension counts for reading lookup table - real(r8), allocatable :: lookup_table(:,:) - logical , allocatable :: valid_entries(:,:) ! which entries of the lookup table are considered valid - - character(len=*), parameter :: subname = 'lookup_2d_netcdf' -!----------------------------------------------------------------------- - - ! Error-check extra_dims - - if (n_extra_dims > 0) then - if (.not. present(extra_dims)) then - write(6,*) subname//' ERROR: extra_dims must be present for n_extra_dims > 0' - call abort() - end if - - if (size(extra_dims) < n_extra_dims) then - write(6,*) subname//' ERROR: not enough extra dimensions given' - write(6,*) 'n_extra_dims = ', n_extra_dims - write(6,*) 'size(extra_dims) = ', size(extra_dims) - call abort() - end if - end if - - ! Determine number of expected dimensions in the table, and actual number of - ! dimensions in the netcdf file - - ndims_expected = 2 + n_extra_dims - - call check_ret(nf_inq_varid (ncid, tablename, varid), subname) - call check_ret(nf_inq_varndims (ncid, varid, ndims), subname) - if (ndims /= ndims_expected) then - write(6,*) subname//' ERROR: unexpected number of dimensions in ', & - trim(tablename) - write(6,*) 'ndims = ', ndims - write(6,*) 'expected (based on n_extra_dims): ', ndims_expected - call abort() - end if - - ! Get dimension names & sizes, and error-check them - - allocate(dimids(ndims), dimlens(ndims), dimnames(ndims)) - call check_ret(nf_inq_vardimid (ncid, varid, dimids), subname) - do i = 1, ndims - call check_ret(nf_inq_dimname (ncid, dimids(i), dimnames(i)), subname) - call check_ret(nf_inq_dimlen (ncid, dimids(i), dimlens(i)), subname) - end do - - call check_dimname(dimnames(1), dimname1, 1) - call check_dimname(dimnames(2), dimname2, 2) - do i = 1, n_extra_dims - call check_dimname(dimnames(2+i), extra_dims(i)%name, 2+i) - call check_dimsize(dimlens(2+i), extra_dims(i)%val, 2+i) - end do - - ! Read the lookup table; if the given variable has more than 2 dimensions, we read - ! a single 2-d slice - - allocate(starts(ndims), counts(ndims)) - allocate(lookup_table(dimlens(1), dimlens(2))) - starts(1:2) = 1 - counts(1:2) = dimlens(1:2) - do i = 1, n_extra_dims - starts(2+i) = extra_dims(i)%val - counts(2+i) = 1 - end do - call check_ret(nf_get_vara_double (ncid, varid, starts, counts, lookup_table), subname) - - ! Determine which entries are valid - - allocate(valid_entries(size(lookup_table, 1), size(lookup_table, 2))) - valid_entries(:,:) = .true. - if (lookup_has_invalid) then - call check_ret(nf_get_att_double (ncid, varid, '_FillValue', table_fillval), subname) - where (lookup_table == table_fillval) - valid_entries = .false. - end where - end if - - ! Do the lookups - - call lookup_2d(index1, index2, lookup_table, fill_val, data, ierr, nodata=nodata, & - valid_entries=valid_entries, invalid_okay=invalid_okay) - - deallocate(valid_entries) - deallocate(lookup_table) - deallocate(starts, counts) - deallocate(dimids, dimlens, dimnames) - -contains -!------------------------------------------------------------------------------ - subroutine check_dimname(actual, expected, i) - ! Make sure names are equal; if not, stop with an error message - - character(len=*), intent(in) :: actual, expected - integer , intent(in) :: i ! dimension number, for output purposes - - if (actual /= expected) then - write(6,*) subname//' ERROR: unexpected dimension name in ', trim(tablename) - write(6,*) 'dimension #', i - write(6,*) 'actual: ', trim(actual) - write(6,*) 'expected: ', trim(expected) - call abort() - end if - end subroutine check_dimname - -!------------------------------------------------------------------------------ - subroutine check_dimsize(length, index, i) - ! Make sure dimension length is long enough; if not, stop with an error message - - integer, intent(in) :: length, index - integer, intent(in) :: i ! dimension number, for output purposes - - if (index > length) then - write(6,*) subname//' ERROR: desired index exceeds dimension length in ', & - trim(tablename) - write(6,*) 'dimension #', i - write(6,*) 'index: ', index - write(6,*) 'length: ', length - call abort() - end if - end subroutine check_dimsize - -end subroutine lookup_2d_netcdf -!------------------------------------------------------------------------------ - -!------------------------------------------------------------------------------ -!BOP -! -! !IROUTINE: which_max -! -! !INTERFACE: -subroutine which_max(arr, maxval, maxindex, lbound) -! -! !DESCRIPTION: -! Returns maximum value in arr along with the index of the maximum value -! -! If multiple values are tied, returns index of the first maximum -! -! !ARGUMENTS: - implicit none - real(r8), intent(in) :: arr(:) - real(r8), intent(out):: maxval ! maximum value in arr(:) - integer , intent(out):: maxindex ! first index of maxval - - ! lower bound of indices of arr; if not supplied, assumed to be 1: - integer , intent(in), optional :: lbound -! -! !REVISION HISTORY: -! Author: Bill Sacks -! -! -! !LOCAL VARIABLES: -!EOP - integer :: i -!----------------------------------------------------------------------- - - maxindex = 1 - maxval = arr(1) - - do i = 2, size(arr) - if (arr(i) > maxval) then - maxindex = i - maxval = arr(i) - end if - end do - - if (present(lbound)) then - maxindex = maxindex + (lbound - 1) - end if -end subroutine which_max -!------------------------------------------------------------------------------ - -end module mkindexmapMod diff --git a/tools/mksurfdata_map/src/mklaiMod.F90 b/tools/mksurfdata_map/src/mklaiMod.F90 deleted file mode 100644 index e4b6d9bfa1..0000000000 --- a/tools/mksurfdata_map/src/mklaiMod.F90 +++ /dev/null @@ -1,445 +0,0 @@ -module mklaiMod -!----------------------------------------------------------------------- -!BOP -! -! !MODULE: mklai -! -! !DESCRIPTION: -! Make LAI/SAI/height data -! -! !REVISION HISTORY: -! Author: Sam Levis -! -!EOP -!----------------------------------------------------------------------- - use shr_kind_mod, only : r8 => shr_kind_r8 - use shr_sys_mod , only : shr_sys_flush - use mkdomainMod , only : domain_checksame - use mkvarctl - - implicit none - - private - - public :: mklai - private :: pft_laicheck - -contains - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: mklai -! -! !INTERFACE: -subroutine mklai(ldomain, mapfname, datfname, ndiag, ncido) -! -! !DESCRIPTION: -! Make LAI/SAI/height data -! Portions of this code could be moved out of the month loop -! for improved efficiency -! -! !USES: - use mkdomainMod, only : domain_type, domain_clean, domain_read - use mkgridmapMod - use mkvarpar , only : re - use mkvarctl - use mkncdio - use mkpftConstantsMod, only : c3cropindex, c3irrcropindex -! -! !ARGUMENTS: - implicit none - type(domain_type), intent(in) :: ldomain - character(len=*) , intent(in) :: mapfname ! input mapping file name - character(len=*) , intent(in) :: datfname ! input data file name - integer , intent(in) :: ndiag ! unit number for diag out - integer , intent(in) :: ncido ! output netcdf file id -! -! !CALLED FROM: -! subroutine mksrfdat in module mksrfdatMod -! -! !REVISION HISTORY: -! Author: Mariana Vertenstein -! -! -! !LOCAL VARIABLES: -!EOP - type(gridmap_type) :: tgridmap - type(domain_type) :: tdomain ! local domain - integer :: numpft_i ! number of plant types on input - real(r8) :: glai_o(0:numpft) ! output grid: global area pfts - real(r8) :: gsai_o(0:numpft) ! output grid: global area pfts - real(r8) :: ghgtt_o(0:numpft) ! output grid: global area pfts - real(r8) :: ghgtb_o(0:numpft) ! output grid: global area pfts - real(r8) :: glai_i(0:numpft) ! input grid: global area pfts - real(r8) :: gsai_i(0:numpft) ! input grid: global area pfts - real(r8) :: ghgtt_i(0:numpft) ! input grid: global area pfts - real(r8) :: ghgtb_i(0:numpft) ! input grid: global area pfts - - real(r8), allocatable :: mlai_o(:,:) ! monthly lai - real(r8), allocatable :: msai_o(:,:) ! monthly sai - real(r8), allocatable :: mhgtt_o(:,:) ! monthly height (top) - real(r8), allocatable :: mhgtb_o(:,:) ! monthly height (bottom) - real(r8), allocatable :: mlai_max(:,:) ! monthly lai - real(r8), allocatable :: msai_max(:,:) ! monthly sai - real(r8), allocatable :: mhgtt_max(:,:) ! monthly height (top) - real(r8), allocatable :: mhgtb_max(:,:) ! monthly height (bottom) - real(r8), allocatable :: mlai_i(:,:) ! monthly lai in - real(r8), allocatable :: msai_i(:,:) ! monthly sai in - real(r8), allocatable :: mhgtt_i(:,:) ! monthly height (top) in - real(r8), allocatable :: mhgtb_i(:,:) ! monthly height (bottom) in - real(r8), allocatable :: frac_dst(:) ! output fractions: same as frac_dst - integer, pointer :: laimask(:,:) ! lai+sai output mask for each plant function type - real(r8) :: garea_i ! input grid: global area - real(r8) :: garea_o ! output grid: global area - integer :: mwts ! number of weights - integer :: ni,no,ns_i,ns_o ! indices - integer :: k,l,n,m ! indices - integer :: ncidi,dimid,varid ! input netCDF id's - integer :: ndimsi,ndimso ! netCDF dimension sizes - integer :: dimids(4) ! netCDF dimension ids - integer :: bego(4),leno(4) ! netCDF bounds - integer :: begi(4),leni(4) ! netCDF bounds - integer :: ntim ! number of input time samples - integer :: ier ! error status - real(r8) :: relerr = 0.00001 ! max error: sum overlap wts ne 1 - character(len=256) :: name ! name of attribute - character(len=256) :: unit ! units of attribute - character(len= 32) :: subname = 'mklai' -!----------------------------------------------------------------------- - - write (6,*) 'Attempting to make LAIs/SAIs/heights .....' - call shr_sys_flush(6) - - ! ----------------------------------------------------------------- - ! Read input file - ! ----------------------------------------------------------------- - - ! Obtain input grid info, read local fields - - ns_o = ldomain%ns - - call domain_read(tdomain,datfname) - ns_i = tdomain%ns - - write (6,*) 'Open LAI file: ', trim(datfname) - call check_ret(nf_open(datfname, 0, ncidi), subname) - call check_ret(nf_inq_dimid(ncidi, 'pft', dimid), subname) - call check_ret(nf_inq_dimlen(ncidi, dimid, numpft_i), subname) - call check_ret(nf_inq_dimid(ncidi, 'time', dimid), subname) - call check_ret(nf_inq_dimlen(ncidi, dimid, ntim), subname) - - if (numpft_i /= numpft+1) then - write(6,*) 'WARNING: ' // trim(subname) // '(): parameter numpft+1 = ', numpft+1, & - 'does not equal input dataset numpft = ', numpft_i - write(6,*)'This inconsistency used to stop the program. Now we allow it ' - write(6,*)'because crop pfts 17-last are assumed to never use satellite lai data.' -! stop - if (numpft_i > numpft + 1) then - ! NOTE(bja, 2015-01) If this error check is determined to be - ! invalid, all the loop bounds over output data in this - ! routine will need to be double checked! - write(6, *) "ERROR:" // trim(subname) // "(): input numpft must be less than or equal to output numpft+1." - call abort() - end if - endif - if (ntim /= 12) then - write(6,*)'MKLAI: must have 12 time samples on input data' - call abort() - endif - - ! NOTE - close data set at bottom of routine - - ! Dynamic allocation of variables - - allocate(mlai_i(ns_i,0:numpft_i), & - msai_i(ns_i,0:numpft_i), & - mhgtt_i(ns_i,0:numpft_i), & - mhgtb_i(ns_i,0:numpft_i), & - frac_dst(ns_o), & - mlai_o(ns_o,0:numpft), & - msai_o(ns_o,0:numpft), & - mhgtt_o(ns_o,0:numpft), & - mhgtb_o(ns_o,0:numpft), & - laimask(ns_i,0:numpft), stat=ier ) - if (ier /= 0) then - write(6,*)'mklai allocation error'; call abort() - end if - - ! Determine mapping weights and map - - call gridmap_mapread(tgridmap, mapfname) - - ! Error checks for domain and map consistencies - - call domain_checksame( tdomain, ldomain, tgridmap ) - - ! Determine number of dimensions in input by querying MONTHLY_LAI - - call check_ret(nf_inq_varid(ncidi, 'MONTHLY_LAI', varid), subname) - call check_ret(nf_inq_vardimid(ncidi, varid, dimids), subname) - call check_ret(nf_inq_varndims(ncidi, varid, ndimsi), subname) - if (ndimsi ==4) then - begi(1) = 1 - begi(2) = 1 - begi(3) = 1 - leni(4) = 1 - call check_ret(nf_inq_dimlen(ncidi, dimids(1), leni(1)), subname) - call check_ret(nf_inq_dimlen(ncidi, dimids(2), leni(2)), subname) - call check_ret(nf_inq_dimlen(ncidi, dimids(3), leni(3)), subname) - else if (ndimsi== 3) then - begi(1) = 1 - begi(2) = 1 - leni(3) = 1 - call check_ret(nf_inq_dimlen(ncidi, dimids(1), leni(1)), subname) - call check_ret(nf_inq_dimlen(ncidi, dimids(2), leni(2)), subname) - end if - - ! Determine number of dimensions in output by querying MONTHLY_LAI - - call check_ret(nf_inq_varid(ncido, 'MONTHLY_LAI', varid), subname) - call check_ret(nf_inq_varndims(ncido, varid, ndimso), subname) - call check_ret(nf_inq_vardimid(ncido, varid, dimids), subname) - if (ndimso ==4) then - bego(1) = 1 - bego(2) = 1 - bego(3) = 1 - leno(4) = 1 - call check_ret(nf_inq_dimlen(ncido, dimids(1), leno(1)), subname) - call check_ret(nf_inq_dimlen(ncido, dimids(2), leno(2)), subname) - call check_ret(nf_inq_dimlen(ncido, dimids(3), leno(3)), subname) - else if (ndimso== 3) then - bego(1) = 1 - bego(2) = 1 - leno(3) = 1 - call check_ret(nf_inq_dimlen(ncido, dimids(1), leno(1)), subname) - call check_ret(nf_inq_dimlen(ncido, dimids(2), leno(2)), subname) - end if - - ! Loop over months - - do m = 1, ntim - - if (ndimsi == 4) begi(4)=m - if (ndimsi == 3) begi(3)=m - - call check_ret(nf_inq_varid (ncidi, 'MONTHLY_LAI', varid), subname) - call check_ret(nf_get_vara_double (ncidi, varid, begi(1:ndimsi), leni(1:ndimsi), & - mlai_i), subname) - - call check_ret(nf_inq_varid (ncidi, 'MONTHLY_SAI', varid), subname) - call check_ret(nf_get_vara_double (ncidi, varid, begi(1:ndimsi), leni(1:ndimsi), & - msai_i), subname) - - call check_ret(nf_inq_varid (ncidi, 'MONTHLY_HEIGHT_TOP', varid), subname) - call check_ret(nf_get_vara_double (ncidi, varid, begi(1:ndimsi), leni(1:ndimsi), & - mhgtt_i), subname) - - call check_ret(nf_inq_varid (ncidi, 'MONTHLY_HEIGHT_BOT', varid), subname) - call check_ret(nf_get_vara_double (ncidi, varid, begi(1:ndimsi), leni(1:ndimsi), & - mhgtb_i), subname) - - mlai_o(:,:) = 0. - msai_o(:,:) = 0. - mhgtt_o(:,:) = 0. - mhgtb_o(:,:) = 0. - - ! Obtain frac_dst - call gridmap_calc_frac_dst(tgridmap, tdomain%mask, frac_dst) - - ! Loop over pft types to do mapping - do l = 0, numpft_i - 1 - call gridmap_areaave_srcmask(tgridmap, mlai_i(:,l) , mlai_o(:,l) , nodata=0._r8, mask_src=tdomain%mask, frac_dst=frac_dst) - call gridmap_areaave_srcmask(tgridmap, msai_i(:,l) , msai_o(:,l) , nodata=0._r8, mask_src=tdomain%mask, frac_dst=frac_dst) - call gridmap_areaave_srcmask(tgridmap, mhgtt_i(:,l), mhgtt_o(:,l), nodata=0._r8, mask_src=tdomain%mask, frac_dst=frac_dst) - call gridmap_areaave_srcmask(tgridmap, mhgtb_i(:,l), mhgtb_o(:,l), nodata=0._r8, mask_src=tdomain%mask, frac_dst=frac_dst) - enddo - - ! Determine laimask - - laimask(:,:) = 0 - - ! copy LAI, SAI, & heights from the C3 crop (pft15) - ! to the irrigated (pft16) whether crop is on or off - mlai_o(:,c3irrcropindex) = mlai_o(:,c3cropindex) - msai_o(:,c3irrcropindex) = msai_o(:,c3cropindex) - mhgtt_o(:,c3irrcropindex) = mhgtt_o(:,c3cropindex) - mhgtb_o(:,c3irrcropindex) = mhgtb_o(:,c3cropindex) - - ! ----------------------------------------------------------------- - ! Output model resolution LAI/SAI/HEIGHT data - ! ----------------------------------------------------------------- - - ! Now write out all variables - - if (ndimso == 4) bego(4)=m - if (ndimso == 3) bego(3)=m - - call check_ret(nf_inq_varid(ncido, 'MONTHLY_LAI', varid), subname) - call check_ret(nf_put_vara_double(ncido, varid, bego, leno, mlai_o), subname) - - call check_ret(nf_inq_varid(ncido, 'MONTHLY_SAI', varid), subname) - call check_ret(nf_put_vara_double(ncido, varid, bego, leno, msai_o), subname) - - call check_ret(nf_inq_varid(ncido, 'MONTHLY_HEIGHT_TOP', varid), subname) - call check_ret(nf_put_vara_double(ncido, varid, bego, leno, mhgtt_o), subname) - - call check_ret(nf_inq_varid(ncido, 'MONTHLY_HEIGHT_BOT', varid), subname) - call check_ret(nf_put_vara_double(ncido, varid, bego, leno, mhgtb_o), subname) - - call check_ret(nf_inq_varid(ncido, 'time', varid), subname) - call check_ret(nf_put_vara_int(ncido, varid, bego(ndimso), leno(ndimso), m), subname) - - call check_ret(nf_sync(ncido), subname) - - - ! ----------------------------------------------------------------- - ! Error check2 - ! Compare global areas on input and output grids - ! ----------------------------------------------------------------- - - ! Input grid global area - - garea_i = 0. - do ni = 1,ns_i - garea_i = garea_i + tgridmap%area_src(ni) - end do - - glai_i(:) = 0. - gsai_i(:) = 0. - ghgtt_i(:) = 0. - ghgtb_i(:) = 0. - do l = 0, numpft_i - 1 - do ni = 1, ns_i - glai_i(l) = glai_i(l) + mlai_i(ni,l) *tgridmap%area_src(ni)*& - tdomain%mask(ni)*re**2 - gsai_i(l) = gsai_i(l) + msai_i(ni,l) *tgridmap%area_src(ni)*& - tdomain%mask(ni)*re**2 - ghgtt_i(l) = ghgtt_i(l)+ mhgtt_i(ni,l)*tgridmap%area_src(ni)*& - tdomain%mask(ni)*re**2 - ghgtb_i(l) = ghgtb_i(l)+ mhgtb_i(ni,l)*tgridmap%area_src(ni)*& - tdomain%mask(ni)*re**2 - end do - end do - - ! Output grid global area - - garea_o = 0. - do no = 1,ns_o - garea_o = garea_o + tgridmap%area_dst(no) - end do - - glai_o(:) = 0. - gsai_o(:) = 0. - ghgtt_o(:) = 0. - ghgtb_o(:) = 0. - do l = 0, numpft_i - 1 - do no = 1,ns_o - glai_o(l) = glai_o(l) + mlai_o(no,l)*tgridmap%area_dst(no)* & - frac_dst(no)*re**2 - gsai_o(l) = gsai_o(l) + msai_o(no,l)*tgridmap%area_dst(no)* & - frac_dst(no)*re**2 - ghgtt_o(l) = ghgtt_o(l)+ mhgtt_o(no,l)*tgridmap%area_dst(no)* & - frac_dst(no)*re**2 - ghgtb_o(l) = ghgtb_o(l)+ mhgtb_o(no,l)*tgridmap%area_dst(no)* & - frac_dst(no)*re**2 - end do - end do - - ! Comparison - - write (ndiag,*) - write (ndiag,'(1x,70a1)') ('=',k=1,70) - write (ndiag,*) 'LAI Output for month ',m - write (ndiag,'(1x,70a1)') ('=',k=1,70) - - write (ndiag,*) - write (ndiag,'(1x,70a1)') ('.',k=1,70) - write (ndiag,1001) -1001 format (1x,'PFT input grid area output grid area',/ & - 1x,3x,' 10**6 km**2',' 10**6 km**2') - write (ndiag,'(1x,70a1)') ('.',k=1,70) - write (ndiag,*) - do l = 0, numpft - write (ndiag,1002) l, glai_i(l)*1.e-06*1.e-02,glai_o(l)*1.e-06*1.e-02 -1002 format (1x,i3,f16.3,f17.3) - end do - - write (6,*) 'Successfully made LAIs/SAIs/heights for month ', m - call shr_sys_flush(6) - - enddo - write (6,*) - - ! Close input file - call check_ret(nf_close(ncidi), subname) - - ! consistency check that PFT and LAI+SAI make sense - !call pft_laicheck( ni_s, pft_i, laimask ) - - ! Deallocate dynamic memory - deallocate(mlai_i) - deallocate(msai_i) - deallocate(mhgtt_i) - deallocate(mhgtb_i) - deallocate(mlai_o) - deallocate(msai_o) - deallocate(mhgtt_o) - deallocate(mhgtb_o) - deallocate(laimask) - deallocate(frac_dst) - - call gridmap_clean(tgridmap) - call domain_clean(tdomain) - -end subroutine mklai - -!----------------------------------------------------------------------- -!BOP -! -! !INTERFACE: -subroutine pft_laicheck( ni_s, pctpft_i, laimask ) - -! !USES: -! -! !DESCRIPTION: -! -! consistency check that PFT and LAI+SAI make sense -! -! !ARGUMENTS: - implicit none - integer , intent(in) :: ni_s ! input PFT grid resolution - real(r8), pointer :: pctpft_i(:,:) ! % plant function types - integer, pointer :: laimask(:,:) ! mask where LAI+SAI > 0 -!EOP - - character(len=*), parameter :: subName="pft_laicheck" - integer :: ni,l,n,nc ! Indices -!----------------------------------------------------------------------- - - do l = 0, numpft - n = 0 - nc = 0 - do ni = 1,ni_s - if ( pctpft_i(ni,l) > 0.0_r8 ) nc = nc + 1 - if ( (pctpft_i(ni,l) > 0.0_r8) .and. (laimask(ni,l) /= 1) )then - write (6,*) subName//' :: warning: pft and LAI+SAI mask not consistent!' - write (6,*) 'ni,l = ', ni, l - write (6,*) 'pctpft_i = ',pctpft_i(ni,l) - write (6,*) 'laimask = ', laimask(ni,l) - n = n + 1 - end if - end do - if ( n > max(4,nc/4) ) then - write (6,*) subName//' :: pft/LAI+SAI inconsistency over more than 25% land-cover' - write (6,*) '# inconsistent points, total PFT pts, total LAI+SAI pts = ', & - n, nc, sum(laimask(:,l)) - call abort() - end if - end do - -end subroutine pft_laicheck - -!----------------------------------------------------------------------- - -end module mklaiMod diff --git a/tools/mksurfdata_map/src/mklanwatMod.F90 b/tools/mksurfdata_map/src/mklanwatMod.F90 deleted file mode 100644 index 4e1c590803..0000000000 --- a/tools/mksurfdata_map/src/mklanwatMod.F90 +++ /dev/null @@ -1,503 +0,0 @@ -module mklanwatMod - -!----------------------------------------------------------------------- -!BOP -! -! !MODULE: mklanwatMod -! -! !DESCRIPTION: -! make %lake and %wetland from input lake / wetland data -! also make lake parameters -! -! !REVISION HISTORY: -! Author: Mariana Vertenstein -! -!----------------------------------------------------------------------- -! -! !USES: - use shr_kind_mod, only : r8 => shr_kind_r8 - use shr_sys_mod , only : shr_sys_flush - use mkdomainMod , only : domain_checksame - - implicit none - - private - -! !PUBLIC MEMBER FUNCTIONS: - public mklakwat ! make % lake - public mkwetlnd ! make % wetland - public mklakparams ! make lake parameters - -!EOP -!=============================================================== -contains -!=============================================================== - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: mklakwat -! -! !INTERFACE: -subroutine mklakwat(ldomain, mapfname, datfname, ndiag, zero_out, lake_o) -! -! !DESCRIPTION: -! make %lake -! -! !USES: - use mkdomainMod, only : domain_type, domain_clean, domain_read - use mkgridmapMod - use mkvarpar - use mkvarctl - use mkncdio -! -! !ARGUMENTS: - - implicit none - type(domain_type), intent(in) :: ldomain - character(len=*) , intent(in) :: mapfname ! input mapping file name - character(len=*) , intent(in) :: datfname ! input data file name - integer , intent(in) :: ndiag ! unit number for diag out - logical , intent(in) :: zero_out ! if should zero glacier out - real(r8) , intent(out):: lake_o(:) ! output grid: %lake -! -! !CALLED FROM: -! subroutine mksrfdat in module mksrfdatMod -! -! !REVISION HISTORY: -! Author: Mariana Vertenstein -! -! -! !LOCAL VARIABLES: -!EOP - type(gridmap_type) :: tgridmap - type(domain_type) :: tdomain ! local domain - real(r8), allocatable :: lake_i(:) ! input grid: percent lake - real(r8), allocatable :: frac_dst(:) ! output fractions - real(r8), allocatable :: mask_r8(:) ! float of tdomain%mask - real(r8) :: sum_fldi ! global sum of dummy input fld - real(r8) :: sum_fldo ! global sum of dummy output fld - real(r8) :: glake_i ! input grid: global lake - real(r8) :: garea_i ! input grid: global area - real(r8) :: glake_o ! output grid: global lake - real(r8) :: garea_o ! output grid: global area - integer :: ni,no,k,n,m,ns_i,ns_o ! indices - integer :: ncid,dimid,varid ! input netCDF id's - integer :: ier ! error status - real(r8) :: relerr = 0.00001 ! max error: sum overlap wts ne 1 - character(len=32) :: subname = 'mklakwat' -!----------------------------------------------------------------------- - - write (6,*) 'Attempting to make %lake and %wetland .....' - call shr_sys_flush(6) - - ! ----------------------------------------------------------------- - ! Read input file - ! ----------------------------------------------------------------- - - ! Obtain input grid info, read local fields - - ns_o = ldomain%ns - - call domain_read(tdomain,datfname) - ns_i = tdomain%ns - - if ( .not. zero_out )then - allocate(lake_i(ns_i), stat=ier) - if (ier/=0) call abort() - allocate(frac_dst(ns_o), stat=ier) - if (ier/=0) call abort() - - write(6,*)'Open lake file: ', trim(datfname) - call check_ret(nf_open(datfname, 0, ncid), subname) - call check_ret(nf_inq_varid (ncid, 'PCT_LAKE', varid), subname) - call check_ret(nf_get_var_double (ncid, varid, lake_i), subname) - call check_ret(nf_close(ncid), subname) - - ! Area-average percent cover on input grid to output grid - ! and correct according to land landmask - ! Note that percent cover is in terms of total grid area. - - call gridmap_mapread(tgridmap, mapfname ) - - ! Error checks for domain and map consistencies - - call domain_checksame( tdomain, ldomain, tgridmap ) - - ! Obtain frac_dst - call gridmap_calc_frac_dst(tgridmap, tdomain%mask, frac_dst) - - ! Determine lake_o on output grid - - call gridmap_areaave_srcmask(tgridmap, lake_i,lake_o, nodata=0._r8, mask_src=tdomain%mask, frac_dst=frac_dst) - - do no = 1,ns_o - if (lake_o(no) < 1.) lake_o(no) = 0. - enddo - - ! ----------------------------------------------------------------- - ! Error check prep - ! Global sum of output field -- must multiply by fraction of - ! output grid that is land as determined by input grid - ! ----------------------------------------------------------------- - - allocate(mask_r8(ns_i), stat=ier) - if (ier/=0) call abort() - mask_r8 = tdomain%mask - call gridmap_check( tgridmap, mask_r8, frac_dst, subname ) - - ! ----------------------------------------------------------------- - ! Error check2 - ! Compare global areas on input and output grids - ! ----------------------------------------------------------------- - - ! Input grid - - glake_i = 0. - garea_i = 0. - do ni = 1,ns_i - garea_i = garea_i + tgridmap%area_src(ni)*re**2 - glake_i = glake_i + lake_i(ni)*tgridmap%area_src(ni)/100.*re**2 - end do - - ! Output grid - - glake_o = 0. - garea_o = 0. - do no = 1,ns_o - garea_o = garea_o + tgridmap%area_dst(no)*re**2 - glake_o = glake_o + lake_o(no)*tgridmap%area_dst(no)/100.*re**2 - end do - - ! Diagnostic output - - write (ndiag,*) - write (ndiag,'(1x,70a1)') ('=',k=1,70) - write (ndiag,*) 'Inland Water Output' - write (ndiag,'(1x,70a1)') ('=',k=1,70) - - write (ndiag,*) - write (ndiag,'(1x,70a1)') ('.',k=1,70) - write (ndiag,2001) -2001 format (1x,'surface type input grid area output grid area'/ & - 1x,' 10**6 km**2 10**6 km**2 ') - write (ndiag,'(1x,70a1)') ('.',k=1,70) - write (ndiag,*) - write (ndiag,2002) glake_i*1.e-06,glake_o*1.e-06 - write (ndiag,2004) garea_i*1.e-06,garea_o*1.e-06 -2002 format (1x,'lakes ',f14.3,f17.3) -2004 format (1x,'all surface ',f14.3,f17.3) - else - do no = 1,ns_o - lake_o(no) = 0. - enddo - end if - - ! Deallocate dynamic memory - - call domain_clean(tdomain) - if ( .not. zero_out )then - call gridmap_clean(tgridmap) - deallocate (lake_i) - deallocate (frac_dst) - deallocate (mask_r8) - end if - - write (6,*) 'Successfully made %lake' - write (6,*) - call shr_sys_flush(6) - -end subroutine mklakwat - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: mkwetlnd -! -! !INTERFACE: -subroutine mkwetlnd(ldomain, mapfname, datfname, ndiag, zero_out, swmp_o) -! -! !DESCRIPTION: -! make %wetland -! -! !USES: - use mkdomainMod, only : domain_type, domain_clean, domain_read - use mkgridmapMod - use mkvarpar - use mkvarctl - use mkncdio -! -! !ARGUMENTS: - - implicit none - type(domain_type), intent(in) :: ldomain - character(len=*) , intent(in) :: mapfname ! input mapping file name - character(len=*) , intent(in) :: datfname ! input data file name - integer , intent(in) :: ndiag ! unit number for diag out - logical , intent(in) :: zero_out ! if should zero glacier out - real(r8) , intent(out):: swmp_o(:) ! output grid: %wetland -! -! !CALLED FROM: -! subroutine mksrfdat in module mksrfdatMod -! -! !REVISION HISTORY: -! Author: Mariana Vertenstein -! -! -! !LOCAL VARIABLES: -!EOP - type(gridmap_type) :: tgridmap - type(domain_type) :: tdomain ! local domain - real(r8), allocatable :: swmp_i(:) ! input grid: percent swamp - real(r8), allocatable :: frac_dst(:) ! output fractions - real(r8), allocatable :: mask_r8(:) ! float of tdomain%mask - real(r8) :: sum_fldi ! global sum of dummy input fld - real(r8) :: sum_fldo ! global sum of dummy output fld - real(r8) :: gswmp_i ! input grid: global swamp - real(r8) :: garea_i ! input grid: global area - real(r8) :: gswmp_o ! output grid: global swamp - real(r8) :: garea_o ! output grid: global area - integer :: ni,no,k,n,m,ns_i,ns_o ! indices - integer :: ncid,dimid,varid ! input netCDF id's - integer :: ier ! error status - real(r8) :: relerr = 0.00001 ! max error: sum overlap wts ne 1 - character(len=32) :: subname = 'mkwetlnd' -!----------------------------------------------------------------------- - - write (6,*) 'Attempting to make %wetland .....' - call shr_sys_flush(6) - - ! ----------------------------------------------------------------- - ! Read input file - ! ----------------------------------------------------------------- - - ! Obtain input grid info, read local fields - - ns_o = ldomain%ns - - call domain_read(tdomain,datfname) - ns_i = tdomain%ns - - if ( .not. zero_out )then - allocate(swmp_i(ns_i), stat=ier) - if (ier/=0) call abort() - allocate(frac_dst(ns_o), stat=ier) - if (ier/=0) call abort() - - write(6,*)'Open wetland file: ', trim(datfname) - call check_ret(nf_open(datfname, 0, ncid), subname) - call check_ret(nf_inq_varid (ncid, 'PCT_WETLAND', varid), subname) - call check_ret(nf_get_var_double (ncid, varid, swmp_i), subname) - call check_ret(nf_close(ncid), subname) - - ! Area-average percent cover on input grid to output grid - ! and correct according to land landmask - ! Note that percent cover is in terms of total grid area. - - call gridmap_mapread(tgridmap, mapfname ) - - ! Error checks for domain and map consistencies - - call domain_checksame( tdomain, ldomain, tgridmap ) - - ! Obtain frac_dst - call gridmap_calc_frac_dst(tgridmap, tdomain%mask, frac_dst) - - ! Determine swmp_o on output grid - - call gridmap_areaave_srcmask(tgridmap, swmp_i, swmp_o, nodata=0._r8, mask_src=tdomain%mask, frac_dst=frac_dst) - - do no = 1,ns_o - if (swmp_o(no) < 1.) swmp_o(no) = 0. - enddo - - ! ----------------------------------------------------------------- - ! Error check prep - ! Global sum of output field -- must multiply by fraction of - ! output grid that is land as determined by input grid - ! ----------------------------------------------------------------- - - allocate(mask_r8(ns_i), stat=ier) - if (ier/=0) call abort() - mask_r8 = tdomain%mask - call gridmap_check( tgridmap, mask_r8, frac_dst, subname ) - - ! ----------------------------------------------------------------- - ! Error check2 - ! Compare global areas on input and output grids - ! ----------------------------------------------------------------- - - ! Input grid - - gswmp_i = 0. - garea_i = 0. - do ni = 1,ns_i - garea_i = garea_i + tgridmap%area_src(ni)*re**2 - gswmp_i = gswmp_i + swmp_i(ni)*tgridmap%area_src(ni)/100.*re**2 - end do - - ! Output grid - - gswmp_o = 0. - garea_o = 0. - do no = 1,ns_o - garea_o = garea_o + tgridmap%area_dst(no)*re**2 - gswmp_o = gswmp_o + swmp_o(no)*tgridmap%area_dst(no)/100.*re**2 - end do - - ! Diagnostic output - - write (ndiag,*) - write (ndiag,'(1x,70a1)') ('=',k=1,70) - write (ndiag,*) 'Inland Water Output' - write (ndiag,'(1x,70a1)') ('=',k=1,70) - - write (ndiag,*) - write (ndiag,'(1x,70a1)') ('.',k=1,70) - write (ndiag,2001) -2001 format (1x,'surface type input grid area output grid area'/ & - 1x,' 10**6 km**2 10**6 km**2 ') - write (ndiag,'(1x,70a1)') ('.',k=1,70) - write (ndiag,*) - write (ndiag,2003) gswmp_i*1.e-06,gswmp_o*1.e-06 - write (ndiag,2004) garea_i*1.e-06,garea_o*1.e-06 -2003 format (1x,'wetlands ',f14.3,f17.3) -2004 format (1x,'all surface ',f14.3,f17.3) - else - do no = 1,ns_o - swmp_o(no) = 0. - enddo - end if - - ! Deallocate dynamic memory - - call domain_clean(tdomain) - if ( .not. zero_out )then - call gridmap_clean(tgridmap) - deallocate (swmp_i) - deallocate (frac_dst) - deallocate (mask_r8) - end if - - write (6,*) 'Successfully made %wetland' - write (6,*) - call shr_sys_flush(6) - -end subroutine mkwetlnd - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: mklakparams -! -! !INTERFACE: -subroutine mklakparams(ldomain, mapfname, datfname, ndiag, & - lakedepth_o) -! -! !DESCRIPTION: -! make lake parameters (currently just lake depth) -! -! !USES: - use mkdomainMod, only : domain_type, domain_clean, domain_read - use mkgridmapMod - use mkncdio - use mkdiagnosticsMod, only : output_diagnostics_continuous - use mkchecksMod, only : min_bad -! -! !ARGUMENTS: - - implicit none - type(domain_type) , intent(in) :: ldomain - character(len=*) , intent(in) :: mapfname ! input mapping file name - character(len=*) , intent(in) :: datfname ! input data file name - integer , intent(in) :: ndiag ! unit number for diag out - real(r8) , intent(out):: lakedepth_o(:) ! output grid: lake depth (m) -! -! !CALLED FROM: -! subroutine mksrfdat in module mksrfdatMod -! -! !REVISION HISTORY: -! Author: Bill Sacks -! -! -! !LOCAL VARIABLES: -!EOP - type(gridmap_type) :: tgridmap - type(domain_type) :: tdomain ! local domain - real(r8), allocatable :: data_i(:) ! data on input grid - real(r8), allocatable :: frac_dst(:) ! output fractions - real(r8), allocatable :: mask_r8(:) ! float of tdomain%mask - integer :: ncid,varid ! input netCDF id's - integer :: ier ! error status - - real(r8), parameter :: min_valid_lakedepth = 0._r8 - - character(len=32) :: subname = 'mklakparams' -!----------------------------------------------------------------------- - - write (6,*) 'Attempting to make lake parameters.....' - call shr_sys_flush(6) - - ! ----------------------------------------------------------------- - ! Read domain and mapping information, check for consistency - ! ----------------------------------------------------------------- - - call domain_read(tdomain,datfname) - - call gridmap_mapread(tgridmap, mapfname ) - - ! Obtain frac_dst - allocate(frac_dst(ldomain%ns), stat=ier) - if (ier/=0) call abort() - call gridmap_calc_frac_dst(tgridmap, tdomain%mask, frac_dst) - - allocate(mask_r8(tdomain%ns), stat=ier) - if (ier/=0) call abort() - mask_r8 = tdomain%mask - call gridmap_check( tgridmap, mask_r8, frac_dst, subname ) - - call domain_checksame( tdomain, ldomain, tgridmap ) - - ! ----------------------------------------------------------------- - ! Open input file, allocate memory for input data - ! ----------------------------------------------------------------- - - write(6,*)'Open lake parameter file: ', trim(datfname) - call check_ret(nf_open(datfname, 0, ncid), subname) - - allocate(data_i(tdomain%ns), stat=ier) - if (ier/=0) call abort() - - ! ----------------------------------------------------------------- - ! Regrid lake depth - ! ----------------------------------------------------------------- - - call check_ret(nf_inq_varid (ncid, 'LAKEDEPTH', varid), subname) - call check_ret(nf_get_var_double (ncid, varid, data_i), subname) - call gridmap_areaave_srcmask(tgridmap, data_i, lakedepth_o, nodata=10._r8, mask_src=tdomain%mask, frac_dst=frac_dst) - - ! Check validity of output data - if (min_bad(lakedepth_o, min_valid_lakedepth, 'lakedepth')) then - call abort() - end if - - call output_diagnostics_continuous(data_i, lakedepth_o, tgridmap, "Lake Depth", "m", ndiag, tdomain%mask, frac_dst) - - ! ----------------------------------------------------------------- - ! Close files and deallocate dynamic memory - ! ----------------------------------------------------------------- - - call check_ret(nf_close(ncid), subname) - call domain_clean(tdomain) - call gridmap_clean(tgridmap) - deallocate (data_i) - deallocate (frac_dst) - deallocate (mask_r8) - - write (6,*) 'Successfully made lake parameters' - write (6,*) - call shr_sys_flush(6) - -end subroutine mklakparams - -end module mklanwatMod diff --git a/tools/mksurfdata_map/src/mkncdio.F90 b/tools/mksurfdata_map/src/mkncdio.F90 deleted file mode 100644 index 555eb6ae80..0000000000 --- a/tools/mksurfdata_map/src/mkncdio.F90 +++ /dev/null @@ -1,558 +0,0 @@ -module mkncdio - -!----------------------------------------------------------------------- -!BOP -! -! !MODULE: mkncdio -! -! !DESCRIPTION: -! Generic interfaces to write fields to netcdf files, and other useful netcdf operations -! -! !USES: - use shr_kind_mod , only : r8 => shr_kind_r8 - use shr_sys_mod , only : shr_sys_flush -! -! !PUBLIC TYPES: - implicit none - include 'netcdf.inc' - save - - private - - public :: check_ret ! checks return status of netcdf calls - public :: ncd_defvar ! define netCDF input variable - public :: ncd_def_spatial_var ! define spatial netCDF variable (convenience wrapper to ncd_defvar) - public :: ncd_put_time_slice ! write a single time slice of a variable - public :: get_dim_lengths ! get dimension lengths of a netcdf variable - - interface ncd_def_spatial_var - module procedure ncd_def_spatial_var_0lev - module procedure ncd_def_spatial_var_1lev - module procedure ncd_def_spatial_var_2lev - end interface ncd_def_spatial_var - - interface ncd_put_time_slice - module procedure ncd_put_time_slice_1d - module procedure ncd_put_time_slice_2d - end interface ncd_put_time_slice - - public :: convert_latlon ! convert a latitude or longitude variable to degrees E / N -! -! !REVISION HISTORY: -! -! -! !PRIVATE MEMBER FUNCTIONS: -! - private :: get_time_slice_beg_and_len ! determine beg and len vectors for writing a time slice - - logical :: masterproc = .true. ! always use 1 proc - real(r8) :: spval = 1.e36 ! special value - - public :: nf_open - public :: nf_close - public :: nf_write - public :: nf_sync - public :: nf_inq_attlen - public :: nf_inq_dimlen - public :: nf_inq_dimname - public :: nf_inq_varid - public :: nf_inq_varndims - public :: nf_inq_vardimid - public :: nf_get_att_double - public :: nf_get_att_text - public :: nf_get_var_double - public :: nf_get_vara_double - public :: nf_get_var_int - public :: nf_get_vara_int - public :: nf_put_var_double - public :: nf_put_vara_double - public :: nf_put_var_int - public :: nf_put_vara_int - public :: nf_inq_dimid - public :: nf_max_name - public :: nf_max_var_dims - public :: nf_noerr - public :: nf_nowrite - public :: nf_enotatt - public :: nf_strerror -!EOP -!----------------------------------------------------------------------- - -contains - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: check_ret -! -! !INTERFACE: - subroutine check_ret(ret, calling, varexists) -! -! !DESCRIPTION: -! Check return status from netcdf call -! -! !ARGUMENTS: - implicit none - integer, intent(in) :: ret - character(len=*) :: calling - logical, intent(out), optional :: varexists -! -! !REVISION HISTORY: -! -!EOP -!----------------------------------------------------------------------- - - if ( present(varexists) ) varexists = .true. - if ( present(varexists) .and. ret == NF_ENOTVAR )then - varexists = .false. - else if (ret /= NF_NOERR) then - write(6,*)'netcdf error from ',trim(calling), ' rcode = ', ret, & - ' error = ', NF_STRERROR(ret) - call abort() - end if - - end subroutine check_ret - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: ncd_defvar -! -! !INTERFACE: - subroutine ncd_defvar(ncid, varname, xtype, & - dim1name, dim2name, dim3name, dim4name, dim5name, & - long_name, units, cell_method, missing_value, fill_value, & - imissing_value, ifill_value) -! -! !DESCRIPTION: -! Define a netcdf variable -! -! !ARGUMENTS: - implicit none - integer , intent(in) :: ncid ! input unit - character(len=*), intent(in) :: varname ! variable name - integer , intent(in) :: xtype ! external type - character(len=*), intent(in), optional :: dim1name ! dimension name - character(len=*), intent(in), optional :: dim2name ! dimension name - character(len=*), intent(in), optional :: dim3name ! dimension name - character(len=*), intent(in), optional :: dim4name ! dimension name - character(len=*), intent(in), optional :: dim5name ! dimension name - character(len=*), intent(in), optional :: long_name ! attribute - character(len=*), intent(in), optional :: units ! attribute - character(len=*), intent(in), optional :: cell_method ! attribute - real(r8) , intent(in), optional :: missing_value ! attribute for real - real(r8) , intent(in), optional :: fill_value ! attribute for real - integer , intent(in), optional :: imissing_value ! attribute for int - integer , intent(in), optional :: ifill_value ! attribute for int -! -! !REVISION HISTORY: -! -! -! !LOCAL VARIABLES: -!EOP - integer :: n ! indices - integer :: ndims ! dimension counter - integer :: dimid(5) ! dimension ids - integer :: varid ! variable id - integer :: itmp ! temporary - character(len=256) :: str ! temporary - character(len=32) :: subname='NCD_DEFVAR_REAL' ! subroutine name -!----------------------------------------------------------------------- - - if (.not. masterproc) return - - ! Determine dimension ids for variable - - dimid(:) = 0 - - if (present(dim1name)) then - call check_ret(nf_inq_dimid(ncid, dim1name, dimid(1)), subname) - end if - if (present(dim2name)) then - call check_ret(nf_inq_dimid(ncid, dim2name, dimid(2)), subname) - end if - if (present(dim3name)) then - call check_ret(nf_inq_dimid(ncid, dim3name, dimid(3)), subname) - end if - if (present(dim4name)) then - call check_ret(nf_inq_dimid(ncid, dim4name, dimid(4)), subname) - end if - if (present(dim5name)) then - call check_ret(nf_inq_dimid(ncid, dim5name, dimid(5)), subname) - end if - - ! Define variable - - if (present(dim1name)) then - ndims = 0 - do n = 1, size(dimid) - if (dimid(n) /= 0) ndims = ndims + 1 - end do - call check_ret(nf_def_var(ncid, trim(varname), xtype, ndims, dimid(1:ndims), varid), subname) - else - call check_ret(nf_def_var(ncid, varname, xtype, 0, 0, varid), subname) - end if - if (present(long_name)) then - call check_ret(nf_put_att_text(ncid, varid, 'long_name', len_trim(long_name), trim(long_name)), subname) - end if - if (present(units)) then - call check_ret(nf_put_att_text(ncid, varid, 'units', len_trim(units), trim(units)), subname) - end if - if (present(cell_method)) then - str = 'time: ' // trim(cell_method) - call check_ret(nf_put_att_text(ncid, varid, 'cell_method', len_trim(str), trim(str)), subname) - end if - if (present(fill_value)) then - call check_ret(nf_put_att_double(ncid, varid, '_FillValue', xtype, 1, fill_value), subname) - end if - if (present(missing_value)) then - call check_ret(nf_put_att_double(ncid, varid, 'missing_value', xtype, 1, missing_value), subname) - end if - if (present(ifill_value)) then - call check_ret(nf_put_att_int(ncid, varid, '_FillValue', xtype, 1, ifill_value), subname) - end if - if (present(imissing_value)) then - call check_ret(nf_put_att_int(ncid, varid, 'missing_value', xtype, 1, imissing_value), subname) - end if - - end subroutine ncd_defvar - - ! ======================================================================== - ! ncd_def_spatial_var routines: define a spatial netCDF variable (convenience wrapper to - ! ncd_defvar) - ! ======================================================================== - - !----------------------------------------------------------------------- - subroutine ncd_def_spatial_var_0lev(ncid, varname, xtype, long_name, units) - ! - ! !DESCRIPTION: - ! Define a spatial netCDF variable (convenience wrapper to ncd_defvar) - ! - ! The variable in question has ONLY spatial dimensions (no level or time dimensions) - ! - ! !USES: - use mkvarctl, only : outnc_1d - ! - ! !ARGUMENTS: - integer , intent(in) :: ncid ! input unit - character(len=*) , intent(in) :: varname ! variable name - integer , intent(in) :: xtype ! external type - character(len=*) , intent(in) :: long_name ! attribute - character(len=*) , intent(in) :: units ! attribute - ! - ! !LOCAL VARIABLES: - - character(len=*), parameter :: subname = 'ncd_def_spatial_var_0lev' - !----------------------------------------------------------------------- - - if (outnc_1d) then - call ncd_defvar(ncid=ncid, varname=varname, xtype=xtype, & - dim1name='gridcell', & - long_name=long_name, units=units) - else - call ncd_defvar(ncid=ncid, varname=varname, xtype=xtype, & - dim1name='lsmlon', dim2name='lsmlat', & - long_name=long_name, units=units) - end if - - end subroutine ncd_def_spatial_var_0lev - - !----------------------------------------------------------------------- - subroutine ncd_def_spatial_var_1lev(ncid, varname, xtype, lev1name, long_name, units) - ! - ! !DESCRIPTION: - ! Define a spatial netCDF variable (convenience wrapper to ncd_defvar) - ! - ! The variable in question has one level (or time) dimension in addition to its - ! spatial dimensions - ! - ! !USES: - use mkvarctl, only : outnc_1d - ! - ! !ARGUMENTS: - integer , intent(in) :: ncid ! input unit - character(len=*) , intent(in) :: varname ! variable name - integer , intent(in) :: xtype ! external type - character(len=*) , intent(in) :: lev1name ! name of level (or time) dimension - character(len=*) , intent(in) :: long_name ! attribute - character(len=*) , intent(in) :: units ! attribute - ! - ! !LOCAL VARIABLES: - - character(len=*), parameter :: subname = 'ncd_def_spatial_var_1lev' - !----------------------------------------------------------------------- - - if (outnc_1d) then - call ncd_defvar(ncid=ncid, varname=varname, xtype=xtype, & - dim1name='gridcell', dim2name=lev1name, & - long_name=long_name, units=units) - else - call ncd_defvar(ncid=ncid, varname=varname, xtype=xtype, & - dim1name='lsmlon', dim2name='lsmlat',dim3name=lev1name, & - long_name=long_name, units=units) - end if - - end subroutine ncd_def_spatial_var_1lev - - !----------------------------------------------------------------------- - subroutine ncd_def_spatial_var_2lev(ncid, varname, xtype, lev1name, lev2name, long_name, units) - ! - ! !DESCRIPTION: - ! Define a spatial netCDF variable (convenience wrapper to ncd_defvar) - ! - ! The variable in question has two level (or time) dimensions in addition to its - ! spatial dimensions - ! - ! !USES: - use mkvarctl, only : outnc_1d - ! - ! !ARGUMENTS: - integer , intent(in) :: ncid ! input unit - character(len=*) , intent(in) :: varname ! variable name - integer , intent(in) :: xtype ! external type - character(len=*) , intent(in) :: lev1name ! name of first level (or time) dimension - character(len=*) , intent(in) :: lev2name ! name of second level (or time) dimension - character(len=*) , intent(in) :: long_name ! attribute - character(len=*) , intent(in) :: units ! attribute - ! - ! !LOCAL VARIABLES: - - character(len=*), parameter :: subname = 'ncd_def_spatial_var_2lev' - !----------------------------------------------------------------------- - - if (outnc_1d) then - call ncd_defvar(ncid=ncid, varname=varname, xtype=xtype, & - dim1name='gridcell', dim2name=lev1name, dim3name=lev2name, & - long_name=long_name, units=units) - else - call ncd_defvar(ncid=ncid, varname=varname, xtype=xtype, & - dim1name='lsmlon', dim2name='lsmlat', dim3name=lev1name, dim4name=lev2name, & - long_name=long_name, units=units) - end if - - end subroutine ncd_def_spatial_var_2lev - - ! ======================================================================== - ! ncd_put_time_slice routines: write a single time slice of a variable - ! ======================================================================== - - !----------------------------------------------------------------------- - subroutine ncd_put_time_slice_1d(ncid, varid, time_index, data) - ! - ! !DESCRIPTION: - ! Write a single time slice of a 1-d variable - ! - ! !USES: - ! - ! !ARGUMENTS: - integer , intent(in) :: ncid ! netCDF id - integer , intent(in) :: varid ! variable id - integer , intent(in) :: time_index ! time index in file - real(r8), intent(in) :: data(:) ! data to write (a single time slice) - ! - ! !LOCAL VARIABLES: - integer, allocatable :: beg(:) ! begin indices for each dimension - integer, allocatable :: len(:) ! length along each dimension - - character(len=*), parameter :: subname = 'ncd_put_time_slice_1d' - !----------------------------------------------------------------------- - - call get_time_slice_beg_and_len(ncid, varid, time_index, beg, len) - call check_ret(nf_put_vara_double(ncid, varid, beg, len, data), subname) - - deallocate(beg, len) - - end subroutine ncd_put_time_slice_1d - - !----------------------------------------------------------------------- - subroutine ncd_put_time_slice_2d(ncid, varid, time_index, data) - ! - ! !DESCRIPTION: - ! Write a single time slice of a 2-d variable - ! - ! !USES: - ! - ! !ARGUMENTS: - integer , intent(in) :: ncid ! netCDF id - integer , intent(in) :: varid ! variable id - integer , intent(in) :: time_index ! time index in file - real(r8), intent(in) :: data(:,:) ! data to write (a single time slice) - ! - ! !LOCAL VARIABLES: - integer, allocatable :: beg(:) ! begin indices for each dimension - integer, allocatable :: len(:) ! length along each dimension - - character(len=*), parameter :: subname = 'ncd_put_time_slice_2d' - !----------------------------------------------------------------------- - - call get_time_slice_beg_and_len(ncid, varid, time_index, beg, len) - call check_ret(nf_put_vara_double(ncid, varid, beg, len, data), subname) - - deallocate(beg, len) - - end subroutine ncd_put_time_slice_2d - - - !----------------------------------------------------------------------- - subroutine get_time_slice_beg_and_len(ncid, varid, time_index, beg, len) - ! - ! !DESCRIPTION: - ! Determine beg and len vectors for writing a time slice. - ! - ! Assumes time is the last dimension of the given variable. - ! - ! Allocates memory for beg & len. - ! - ! !USES: - ! - ! !ARGUMENTS: - integer , intent(in) :: ncid ! netcdf ID - integer , intent(in) :: varid ! variable ID - integer , intent(in) :: time_index ! time index in file - integer, allocatable, intent(out) :: beg(:) ! begin indices for each dimension - integer, allocatable, intent(out) :: len(:) ! length along each dimension - ! - ! !LOCAL VARIABLES: - integer :: n ! index - integer :: ndims ! number of dimensions - integer, allocatable :: dimids(:) ! dimension IDs - - character(len=*), parameter :: subname = 'get_time_slice_beg_and_len' - !----------------------------------------------------------------------- - - call check_ret(nf_inq_varndims(ncid, varid, ndims), subname) - allocate(beg(ndims)) - allocate(len(ndims)) - allocate(dimids(ndims)) - - call check_ret(nf_inq_vardimid(ncid, varid, dimids), subname) - beg(1:ndims-1) = 1 - do n = 1,ndims-1 - call check_ret(nf_inq_dimlen(ncid, dimids(n), len(n)), subname) - end do - len(ndims) = 1 - beg(ndims) = time_index - - deallocate(dimids) - - end subroutine get_time_slice_beg_and_len - - - - -!------------------------------------------------------------------------------ -!BOP -! -! !IROUTINE: get_dim_lengths -! -! !INTERFACE: -subroutine get_dim_lengths(ncid, varname, ndims, dim_lengths) -! -! !DESCRIPTION: -! Returns the number of dimensions and an array containing the dimension lengths of a -! variable in an open netcdf file. -! -! Entries 1:ndims in the returned dim_lengths array contain the dimension lengths; the -! remaining entries in that vector are meaningless. The dim_lengths array must be large -! enough to hold all ndims values; if not, the code aborts (this can be ensured by passing -! in an array of length nf_max_var_dims). -! -! !USES: -! -! !ARGUMENTS: - implicit none - integer , intent(in) :: ncid ! netcdf id of an open netcdf file - character(len=*), intent(in) :: varname ! name of variable of interest - integer , intent(out):: ndims ! number of dimensions of variable - integer , intent(out):: dim_lengths(:) ! lengths of dimensions of variable -! -! !REVISION HISTORY: -! Author: Bill Sacks -! -! -! !LOCAL VARIABLES: - integer :: varid - integer :: dimids(size(dim_lengths)) - integer :: i - character(len=*), parameter :: subname = 'get_dim_lengths' -!EOP -!------------------------------------------------------------------------------ - call check_ret(nf_inq_varid(ncid, varname, varid), subname) - call check_ret(nf_inq_varndims(ncid, varid, ndims), subname) - - if (ndims > size(dim_lengths)) then - write(6,*) trim(subname), ' ERROR: dim_lengths too small' - call abort() - end if - - call check_ret(nf_inq_vardimid(ncid, varid, dimids), subname) - - dim_lengths(:) = 0 ! pre-fill with 0 so we won't have garbage in elements past ndims - do i = 1, ndims - call check_ret(nf_inq_dimlen(ncid, dimids(i), dim_lengths(i)), subname) - end do - end subroutine get_dim_lengths - -!---------------------------------------------------------------------------- -!BOP -! -! !IROUTINE: convert_latlon -! -! !INTERFACE: - subroutine convert_latlon(ncid, varname, data) -! -! !DESCRIPTION: -! Convert a latitude or longitude variable from its units in the input file to degrees E / -! degrees N. Currently, this just handles conversions from radians to degrees. -! -! Assumes that the longitude / latitude variable has already been read from file, into -! the variable given by 'data'. ncid & varname give the file ID and variable name from -! which this variable was read (needed to obtain the variable's units). -! -! !USES: - use shr_const_mod, only : SHR_CONST_PI -! -! !ARGUMENTS: - implicit none - integer , intent(in) :: ncid ! ID of open netcdf file - character(len=*), intent(in) :: varname ! name of lat or lon variable that was read into 'data' - real(r8) , intent(inout):: data(:) ! latitude or longitude data -! -! !REVISION HISTORY: -! Author: Bill Sacks -! -! -! !LOCAL VARIABLES: -!EOP - integer :: ier ! error return code - integer :: varid ! netCDF variable id - integer :: units_len ! length of units attribute on file - character(len=256) :: units ! units attribute - character(len= 32) :: subname = 'convert_latlon' -!----------------------------------------------------------------- - - call check_ret(nf_inq_varid (ncid, varname, varid), subname) - ier = nf_inq_attlen(ncid, varid, 'units', units_len) - - ! Only do the following processing if there is no error; if ier /= NF_NOERR, that - ! probably means there isn't a units attribute -- in that case, assume units are - ! degrees and need no conversion - if (ier == NF_NOERR) then - if (units_len > len(units)) then - write(6,*) trim(subname), ' ERROR: units variable not long enough to hold attributue' - call abort() - end if - - call check_ret(nf_get_att_text(ncid, varid, 'units', units), subname) - - if (units(1:7) == 'radians') then - ! convert from radians to degrees - data(:) = data(:) * 180._r8 / SHR_CONST_PI - end if - end if - - end subroutine convert_latlon -!------------------------------------------------------------------------------ - - -end module mkncdio diff --git a/tools/mksurfdata_map/src/mkpeatMod.F90 b/tools/mksurfdata_map/src/mkpeatMod.F90 deleted file mode 100644 index 8e47f5032d..0000000000 --- a/tools/mksurfdata_map/src/mkpeatMod.F90 +++ /dev/null @@ -1,149 +0,0 @@ -module mkpeatMod - -!----------------------------------------------------------------------- -!BOP -! -! !MODULE: mkpeatMod -! -! !DESCRIPTION: -! make fraction peat from input peat data -! -! !REVISION HISTORY: -! Author: Sam Levis and Bill Sacks -! -!----------------------------------------------------------------------- -! -! !USES: - use shr_kind_mod, only : r8 => shr_kind_r8 - use shr_sys_mod , only : shr_sys_flush - use mkdomainMod , only : domain_checksame - - implicit none - - private - -! !PUBLIC MEMBER FUNCTIONS: - public mkpeat ! regrid peat data -! -!EOP -!=============================================================== -contains -!=============================================================== - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: mkpeat -! -! !INTERFACE: -subroutine mkpeat(ldomain, mapfname, datfname, ndiag, peat_o) -! -! !DESCRIPTION: -! make peat -! -! !USES: - use mkdomainMod, only : domain_type, domain_clean, domain_read - use mkgridmapMod - use mkncdio - use mkdiagnosticsMod, only : output_diagnostics_area - use mkchecksMod, only : min_bad, max_bad -! -! !ARGUMENTS: - - implicit none - type(domain_type) , intent(in) :: ldomain - character(len=*) , intent(in) :: mapfname ! input mapping file name - character(len=*) , intent(in) :: datfname ! input data file name - integer , intent(in) :: ndiag ! unit number for diag out - real(r8) , intent(out):: peat_o(:) ! output grid: fraction peat -! -! !CALLED FROM: -! subroutine mksrfdat in module mksrfdatMod -! -! !REVISION HISTORY: -! Author: Sam Levis and Bill Sacks -! -! -! !LOCAL VARIABLES: -!EOP - type(gridmap_type) :: tgridmap - type(domain_type) :: tdomain ! local domain - real(r8), allocatable :: data_i(:) ! data on input grid - real(r8), allocatable :: frac_dst(:) ! output fractions - real(r8), allocatable :: mask_r8(:) ! float of tdomain%mask - integer :: ncid,varid ! input netCDF id's - integer :: ier ! error status - - real(r8), parameter :: min_valid = 0._r8 ! minimum valid value - real(r8), parameter :: max_valid = 100.000001_r8 ! maximum valid value - character(len=32) :: subname = 'mkpeat' -!----------------------------------------------------------------------- - - write (6,*) 'Attempting to make peat .....' - call shr_sys_flush(6) - - ! ----------------------------------------------------------------- - ! Read domain and mapping information, check for consistency - ! ----------------------------------------------------------------- - - call domain_read( tdomain, datfname ) - - call gridmap_mapread( tgridmap, mapfname ) - - ! Obtain frac_dst - allocate(frac_dst(ldomain%ns), stat=ier) - if (ier/=0) call abort() - call gridmap_calc_frac_dst(tgridmap, tdomain%mask, frac_dst) - - allocate(mask_r8(tdomain%ns), stat=ier) - if (ier/=0) call abort() - mask_r8 = tdomain%mask - call gridmap_check( tgridmap, mask_r8, frac_dst, subname ) - - call domain_checksame( tdomain, ldomain, tgridmap ) - - ! ----------------------------------------------------------------- - ! Open input file, allocate memory for input data - ! ----------------------------------------------------------------- - - write(6,*)'Open peat file: ', trim(datfname) - call check_ret(nf_open(datfname, 0, ncid), subname) - - allocate(data_i(tdomain%ns), stat=ier) - if (ier/=0) call abort() - - ! ----------------------------------------------------------------- - ! Regrid peat - ! ----------------------------------------------------------------- - - call check_ret(nf_inq_varid (ncid, 'peatf', varid), subname) - call check_ret(nf_get_var_double (ncid, varid, data_i), subname) - call gridmap_areaave_srcmask(tgridmap, data_i, peat_o, nodata=0._r8, mask_src=tdomain%mask, frac_dst=frac_dst) - - ! Check validity of output data - if (min_bad(peat_o, min_valid, 'peat') .or. & - max_bad(peat_o, max_valid, 'peat')) then - call abort() - end if - - call output_diagnostics_area(data_i, peat_o, tgridmap, "Peat", percent=.false., ndiag=ndiag, mask_src=tdomain%mask, frac_dst=frac_dst) - - ! ----------------------------------------------------------------- - ! Close files and deallocate dynamic memory - ! ----------------------------------------------------------------- - - call check_ret(nf_close(ncid), subname) - call domain_clean(tdomain) - call gridmap_clean(tgridmap) - deallocate (data_i) - deallocate (frac_dst) - deallocate (mask_r8) - - write (6,*) 'Successfully made peat' - write (6,*) - call shr_sys_flush(6) - -end subroutine mkpeat - - -end module mkpeatMod diff --git a/tools/mksurfdata_map/src/mkpftMod.F90 b/tools/mksurfdata_map/src/mkpftMod.F90 deleted file mode 100644 index 2eae1ae381..0000000000 --- a/tools/mksurfdata_map/src/mkpftMod.F90 +++ /dev/null @@ -1,1259 +0,0 @@ -module mkpftMod - -!----------------------------------------------------------------------- -!BOP -! -! !MODULE: mkpft -! -! !DESCRIPTION: -! Make PFT data -! -! !REVISION HISTORY: -! Author: Mariana Vertenstein -! -!----------------------------------------------------------------------- -!!USES: - use shr_kind_mod, only : r8 => shr_kind_r8 - use shr_sys_mod , only : shr_sys_flush - use mkvarpar , only : noveg - use mkvarctl , only : numpft - use mkdomainMod , only : domain_checksame - use mkpftConstantsMod - - implicit none - - private ! By default make data private -! -! !PUBLIC MEMBER FUNCTIONS: -! - public mkpftInit ! Initialization - public mkpft ! Set PFT - public mkpft_parse_oride ! Parse the string with PFT fraction/index info to override - public mkpftAtt ! Write out attributes to output file on pft -! -! !PUBLIC DATA MEMBERS: -! - - ! - ! When pft_idx and pft_frc are set, they must be set together, and they will cause the - ! entire area to be covered with vegetation and zero out other landunits. - ! The sum of pft_frc must = 100%, and each pft_idx point in the array corresponds to - ! the fraction in pft_frc. Only the first few points are used until pft_frc = 0.0. - ! - integer :: m ! index - integer, public :: pft_idx(0:maxpft) = & ! PFT vegetation index to override with - (/ ( -1, m = 0, maxpft ) /) - real(r8), public :: pft_frc(0:maxpft) = & ! PFT vegetation fraction to override with - (/ ( 0.0_r8, m = 0, maxpft ) /) -! -! !PRIVATE DATA MEMBERS: -! - logical, public, protected :: use_input_pft = .false. ! Flag to override PFT with input values - logical, public, protected :: presc_cover = .false. ! Flag to prescribe vegetation coverage - integer, private :: nzero ! index of first zero fraction - - type, public :: pft_oride ! Public only for unit testing - real(r8) :: crop ! Percent covered by crops - real(r8) :: natveg ! Percent covered by natural vegetation - real(r8), allocatable :: natpft(:) ! Percent of each natural PFT within the natural veg landunit - real(r8), allocatable :: cft(:) ! Percent of each crop CFT within the crop landunit - contains - procedure, public :: InitZeroOut ! Initialize the PFT override object to zero out all vegetation - procedure, public :: InitAllPFTIndex ! Initialize the PFT override object with PFT indeces for all veg and crop types - procedure, public :: Clean ! Clean up a PFT Override object - end type pft_oride - - interface pft_oride - module procedure :: constructor ! PFT Overide object constructor - end interface pft_oride - - type(pft_oride), private :: pft_override ! Module instance of PFT override object - ! Used for both zeroing out PFT's as well - ! as setting specified PFT's over the gridcell -! -! !PRIVATE MEMBER FUNCTIONS: -! - private :: mkpft_check_oride ! Check the pft_frc and pft_idx values for correctness -!EOP -!=============================================================== -contains -!=============================================================== - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: mkpftInit -! -! !INTERFACE: -subroutine mkpftInit( zero_out_l, all_veg_l ) -! -! !DESCRIPTION: -! Initialize of Make PFT data -! !USES: - use mkvarpar, only : numstdpft, numstdcft -! -! !ARGUMENTS: - implicit none - logical, intent(IN) :: zero_out_l ! If veg should be zero'ed out - logical, intent(IN) :: all_veg_l ! If should zero out other fractions so that - ! all land-cover is vegetation -! -! !CALLED FROM: -! subroutine mksrfdat in module mksrfdatMod -! -! !REVISION HISTORY: -! Author: Erik Kluzek -! -! -! !LOCAL VARIABLES: -!EOP - real(r8), parameter :: hndrd = 100.0_r8 ! A hundred percent - character(len=32) :: subname = 'mkpftMod::mkpftInit() ' - logical :: error_happened ! If an error was triggered so should return -!----------------------------------------------------------------------- - write (6, '(a, a, a)') "In ", trim(subname), "..." - if ( maxpft < numpft ) then - write(6,*) subname//'number PFT is > max allowed!' - call abort() - return - end if - nzero = -1 - call mkpft_check_oride( error_happened ) - if ( error_happened )then - write(6,*) subname//'Problem setting pft override settings' - return - end if - if ( zero_out_l .and. use_input_pft )then - write(6,*) subname//"trying to both zero out all PFT's as well as set them to specific values" - call abort() - return - end if - ! If zeroing out, set use_input_pft to true so the pft_override will be used - if( zero_out_l )then - nzero = 0 - pft_frc(0) = 0.0_r8 - pft_idx(0) = noveg - use_input_pft = .true. - end if - if ( use_input_pft ) then - write(6,*) 'Set PFT fraction to : ', pft_frc(0:nzero) - write(6,*) 'With PFT index : ', pft_idx(0:nzero) - end if - if ( all_veg_l .and. .not. use_input_pft )then - write(6,*) subname//'if all_veg is set to true then specified PFT indices must be provided (i.e. pft_frc and pft_idx)' - call abort() - return - end if - - if ( zero_out_l .and. all_veg_l )then - write(6,*) subname//'zeroing out vegetation and setting vegetation to 100% is a contradiction!' - call abort() - return - end if - - ! Determine number of PFTs on the natural vegetation landunit, and number of CFTs on - ! the crop landunit. - ! - ! For the sake of dynamic PFTs and dynamic landunits, it helps for the structure of the - ! surface dataset to reflect the subgrid structure that will be used by CLM. Currently - ! generic crops will always go on the crop landunit, regardless of whether or not we're - ! using the extra specific crops (so we always run CLM with create_crop_landunit=.true.). - ! When we create a surface dataset WITH the extra specific crops, all crops - ! (including the generic crops) again go on the crop landunit. - - num_natpft = numstdpft - numstdcft - num_cft = numpft - num_natpft - - ! Determine array bounds for arrays of just natural pfts and just crops. Note that - ! these are set up so that they always span 0:numpft, so that there is a 1:1 - ! correspondence between an element in a full 0:numpft array and an element with the - ! same index in either a natpft array or a cft array. - natpft_lb = noveg - natpft_ub = num_natpft - cft_lb = num_natpft+1 - cft_ub = cft_lb + num_cft - 1 - - ! Make sure the array indices have been set up properly, to ensure the 1:1 - ! correspondence mentioned above - if (cft_ub /= numpft) then - write(6,*) 'CFT_UB set up incorrectly: cft_ub, numpft = ', cft_ub, numpft - call abort() - return - end if - ! - ! Set the PFT override values if applicable - ! - pft_override = pft_oride() - presc_cover = .false. - if( zero_out_l )then - call pft_override%InitZeroOut() - presc_cover = .true. - else if ( use_input_pft ) then - call pft_override%InitAllPFTIndex() - if ( .not. all_veg_l )then - if ( pft_override%crop <= 0.0 )then - write(6,*) "Warning: PFT/CFT's are being overridden, but no crop type is being asked for" - end if - if ( pft_override%natveg <= 0.0 )then - write(6,*) "Warning: PFT/CFT's are being overridden, but no natural vegetation type is being asked for" - end if - presc_cover = .false. - else - presc_cover = .true. - end if - end if - -end subroutine mkpftInit - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: mkpft -! -! !INTERFACE: -subroutine mkpft(ldomain, mapfname, fpft, ndiag, & - pctlnd_o, pctnatpft_o, pctcft_o) -! -! !DESCRIPTION: -! Make PFT data -! -! This dataset consists of the %cover of the [numpft]+1 PFTs used by -! the model. The input %cover pertains to the "vegetated" portion of the -! grid cell and sums to 100. The real portion of each grid cell -! covered by each PFT is the PFT cover times the fraction of the -! grid cell that is land. This is the quantity preserved when -! area-averaging from the input (1/2 degree) grid to the models grid. -! -! Upon return from this routine, the % cover of the natural veg + crop landunits is -! generally 100% everywhere; this will be normalized later to account for special landunits. -! -! !USES: - use mkdomainMod, only : domain_type, domain_clean, domain_read - use mkgridmapMod - use mkvarpar - use mkvarctl - use mkncdio - use mkpctPftTypeMod, only : pct_pft_type - use mkpftConstantsMod, only : natpft_lb, natpft_ub, num_cft, cft_lb, cft_ub -! -! !ARGUMENTS: - implicit none - type(domain_type), intent(in) :: ldomain - character(len=*) , intent(in) :: mapfname ! input mapping file name - character(len=*) , intent(in) :: fpft ! input pft dataset file name - integer , intent(in) :: ndiag ! unit number for diag out - real(r8) , intent(out):: pctlnd_o(:) ! output grid:%land/gridcell - type(pct_pft_type), intent(out):: pctnatpft_o(:) ! natural PFT cover - type(pct_pft_type), intent(out):: pctcft_o(:) ! crop (CFT) cover -! -! !CALLED FROM: -! subroutine mksrfdat in module mksrfdatMod -! -! !REVISION HISTORY: -! Author: Mariana Vertenstein -! -! -! !LOCAL VARIABLES: -!EOP - type(pct_pft_type), allocatable:: pctnatpft_i(:) ! input grid: natural PFT cover - type(pct_pft_type), allocatable:: pctcft_i(:) ! input grid: crop (CFT) cover - type(domain_type) :: tdomain ! local domain - type(gridmap_type) :: tgridmap ! local gridmap - real(r8), allocatable :: pctpft_i(:,:) ! input grid: PFT percent - real(r8), allocatable :: pctpft_o(:,:) ! output grid: PFT percent (% of grid cell) - real(r8), allocatable :: pctnatveg_i(:) ! input grid: natural veg percent (% of grid cell) - real(r8), allocatable :: pctnatveg_o(:) ! output grid: natural veg percent (% of grid cell) - real(r8), allocatable :: pctcrop_i(:) ! input grid: all crop percent (% of grid cell) - real(r8), allocatable :: pctcrop_o(:) ! output grid: all crop percent (% of grid cell) - real(r8), allocatable :: frac_dst(:) ! output fractions - real(r8), allocatable :: pct_cft_i(:,:) ! input grid: CFT (Crop Functional Type) percent (% of landunit cell) - real(r8), allocatable :: temp_i(:,:) ! input grid: temporary 2D variable to read in - real(r8), allocatable :: pct_cft_o(:,:) ! output grid: CFT (Crop Functional Type) percent (% of landunit cell) - real(r8), allocatable :: pct_nat_pft_i(:,:) ! input grid: natural PFT percent (% of landunit cell) - real(r8), allocatable :: pct_nat_pft_o(:,:) ! output grid: natural PFT percent (% of landunit cell) - integer :: numpft_i ! num of plant types input data - integer :: natpft_i ! num of natural plant types input data - integer :: ncft_i ! num of crop types input data - real(r8) :: sum_fldo ! global sum of dummy output fld - real(r8) :: sum_fldi ! global sum of dummy input fld - real(r8) :: wst_sum ! sum of %pft - real(r8), allocatable :: gpft_o(:) ! output grid: global area pfts - real(r8) :: garea_o ! output grid: global area - real(r8), allocatable :: gpft_i(:) ! input grid: global area pfts - real(r8) :: garea_i ! input grid: global area - integer :: k,n,m,ni,no,ns_i,ns_o ! indices - integer :: ncid,dimid,varid ! input netCDF id's - integer :: ndims ! number of dimensions for a variable on the file - integer :: dimlens(3) ! dimension lengths for a variable on the file - integer :: ier ! error status - real(r8) :: relerr = 0.0001_r8 ! max error: sum overlap wts ne 1 - logical :: oldformat ! if input file is in the old format or not (based on what variables exist) - logical :: error_happened ! If an error was triggered so should return - - character(len=35) veg(0:maxpft) ! vegetation types - character(len=32) :: subname = 'mkpftMod::mkpft()' -!----------------------------------------------------------------------- - - write (6,*) - write (6, '(a, a, a)') "In ", trim(subname), "..." - write (6,*) 'Attempting to make PFTs .....' - call shr_sys_flush(6) - - ! ----------------------------------------------------------------- - ! Set the vegetation types - ! ----------------------------------------------------------------- - if ( numpft >= numstdpft )then - veg(0:maxpft) = (/ & - 'not vegetated ', & - 'needleleaf evergreen temperate tree', & - 'needleleaf evergreen boreal tree ', & - 'needleleaf deciduous boreal tree ', & - 'broadleaf evergreen tropical tree ', & - 'broadleaf evergreen temperate tree ', & - 'broadleaf deciduous tropical tree ', & - 'broadleaf deciduous temperate tree ', & - 'broadleaf deciduous boreal tree ', & - 'broadleaf evergreen shrub ', & - 'broadleaf deciduous temperate shrub', & - 'broadleaf deciduous boreal shrub ', & - 'c3 arctic grass ', & - 'c3 non-arctic grass ', & - 'c4 grass ', & - 'c3_crop ', & - 'c3_irrigated ', & - 'temperate_corn ', & - 'irrigated_temperate_corn ', & - 'spring_wheat ', & - 'irrigated_spring_wheat ', & - 'winter_wheat ', & - 'irrigated_winter_wheat ', & - 'temperate_soybean ', & - 'irrigated_temperate_soybean ', & - 'barley ', & - 'irrigated_barley ', & - 'winter_barley ', & - 'irrigated_winter_barley ', & - 'rye ', & - 'irrigated_rye ', & - 'winter_rye ', & - 'irrigated_winter_rye ', & - 'cassava ', & - 'irrigated_cassava ', & - 'citrus ', & - 'irrigated citrus ', & - 'cocoa ', & - 'irrigated_cocoa ', & - 'coffee ', & - 'irrigated_coffee ', & - 'cotton ', & - 'irrigated_cotton ', & - 'datepalm ', & - 'irrigated_datepalm ', & - 'foddergrass ', & - 'irrigated_foddergrass ', & - 'grapes ', & - 'irrigated_grapes ', & - 'groundnuts ', & - 'irrigated_groundnuts ', & - 'millet ', & - 'irrigated_millet ', & - 'oilpalm ', & - 'irrigated_oilpalm ', & - 'potatoes ', & - 'irrigated_potatoes ', & - 'pulses ', & - 'irrigated_pulses ', & - 'rapeseed ', & - 'irrigated_rapeseed ', & - 'rice ', & - 'irrigated_rice ', & - 'sorghum ', & - 'irrigated_sorghum ', & - 'sugarbeet ', & - 'irrigated_sugarbeet ', & - 'sugarcane ', & - 'irrigated_sugarcane ', & - 'sunflower ', & - 'irrigated_sunflower ', & - 'miscanthus ', & - 'irrigated_miscanthus ', & - 'switchgrass ', & - 'irrigated_switchgrass ', & - 'tropical_corn ', & - 'irrigated_tropical_corn ', & - 'tropical_soybean ', & - 'irrigated_tropical_soybean ' /) - end if - if ( numpft == numstdpft )then - write(6,*)'Creating surface datasets with the standard # of PFTs =', numpft - else if ( numpft > numstdpft )then - write(6,*)'Creating surface datasets with extra types for crops; total pfts =', numpft - else - write(6,*) subname//': parameter numpft is NOT set to a known value (should be 16 or more) =',numpft - call abort() - return - end if - - ns_o = ldomain%ns - - ! ----------------------------------------------------------------- - ! Read input PFT file - ! ----------------------------------------------------------------- - if ( .not. presc_cover ) then - ! Obtain input grid info, read PCT_PFT - - call domain_read(tdomain,fpft) - ns_i = tdomain%ns - - write (6,*) 'Open PFT file: ', trim(fpft) - call check_ret(nf_open(fpft, 0, ncid), subname) - - ! Check what variables exist to determine what format the file is in - call check_ret(nf_inq_varid (ncid, 'PCT_PFT', varid), subname, varexists=oldformat) - - if ( oldformat ) then - write(6,*) subname//' ERROR: PCT_PFT field on the the file so it is in the old format, which is no longer supported' - call abort() - return - end if - call check_ret(nf_inq_dimid (ncid, 'natpft', dimid), subname) - call check_ret(nf_inq_dimlen (ncid, dimid, natpft_i), subname) - call check_ret(nf_inq_dimid (ncid, 'cft', dimid), subname) - call check_ret(nf_inq_dimlen (ncid, dimid, ncft_i), subname) - numpft_i = natpft_i + ncft_i - - ! Check if the number of pfts on the input matches the expected number. A mismatch - ! is okay if the input raw dataset has prognostic crops and the output does not. - if (numpft_i .ne. numpft+1) then - if (numpft_i .eq. numstdpft+1) then - write(6,*) subname//' ERROR: trying to use non-crop input file' - write(6,*) 'for a surface dataset with crops.' - call abort() - return - else if (numpft_i > numstdpft+1 .and. numpft_i == maxpft+1) then - write(6,*) subname//' WARNING: using a crop input raw dataset for a non-crop output surface dataset' - else - write(6,*) subname//': parameter numpft+1= ',numpft+1, & - 'does not equal input dataset numpft= ',numpft_i - call abort() - return - end if - endif - - - ! If file is in the new format, expect the following variables: - ! PCT_NATVEG, PCT_CROP, PCT_NAT_PFT, PCT_CFT - allocate(pctnatveg_i(ns_i), & - pctnatveg_o(ns_o), & - pctcrop_i(ns_i), & - pctcrop_o(ns_o), & - frac_dst(ns_o), & - pct_cft_i(ns_i,1:num_cft), & - pct_cft_o(ns_o,1:num_cft), & - pct_nat_pft_i(ns_i,0:num_natpft), & - pct_nat_pft_o(ns_o,0:num_natpft), & - stat=ier) - if (ier/=0)then - call abort() - return - end if - - call check_ret(nf_inq_varid (ncid, 'PCT_NATVEG', varid), subname) - call check_ret(nf_get_var_double (ncid, varid, pctnatveg_i), subname) - call check_ret(nf_inq_varid (ncid, 'PCT_CROP', varid), subname) - call check_ret(nf_get_var_double (ncid, varid, pctcrop_i), subname) - if ( .not. use_input_pft )then - call check_ret(nf_inq_varid (ncid, 'PCT_CFT', varid), subname) - call get_dim_lengths(ncid, 'PCT_CFT', ndims, dimlens(:) ) - if ( ndims == 3 .and. dimlens(1)*dimlens(2) == ns_i .and. dimlens(3) == num_cft )then - call check_ret(nf_get_var_double (ncid, varid, pct_cft_i), subname) - else if ( ndims == 3 .and. dimlens(1)*dimlens(2) == ns_i .and. dimlens(3) > num_cft )then - ! Read in the whole array: then sum the rainfed and irrigated - ! seperately - allocate( temp_i(ns_i,dimlens(3)) ) - call check_ret(nf_get_var_double (ncid, varid, temp_i), subname) - do n = 1, num_cft - pct_cft_i(:,n) = 0.0_r8 - do m = n, dimlens(3), 2 - pct_cft_i(:,n) = pct_cft_i(:,n) + temp_i(:,m) - end do - end do - deallocate( temp_i ) - else - write(6,*) subname//': ERROR: dimensions for PCT_CROP are NOT what is expected' - call abort() - return - end if - call check_ret(nf_inq_varid (ncid, 'PCT_NAT_PFT', varid), subname) - call check_ret(nf_get_var_double (ncid, varid, pct_nat_pft_i), subname) - end if - - call check_ret(nf_close(ncid), subname) - - ! ----------------------------------------------------------------- - ! Otherwise if vegetation is prescribed everywhere - ! ----------------------------------------------------------------- - else - ns_i = 1 - numpft_i = numpft+1 - allocate(pctnatveg_i(ns_i), & - pctnatveg_o(ns_o), & - pctcrop_i(ns_i), & - pctcrop_o(ns_o), & - pct_cft_i(ns_i,1:num_cft), & - pct_cft_o(ns_o,1:num_cft), & - pct_nat_pft_i(ns_i,0:num_natpft), & - pct_nat_pft_o(ns_o,0:num_natpft), & - stat=ier) - if (ier/=0)then - call abort() - return - end if - end if - allocate(pctpft_i(ns_i,0:(numpft_i-1)), & - pctpft_o(ns_o,0:(numpft_i-1)), & - pctnatpft_i(ns_i), & - pctcft_i(ns_i), & - stat=ier) - if (ier/=0)then - call abort() - return - end if - - ! Determine pctpft_o on output grid - - ! If total vegetation cover is prescribed from input... - if ( use_input_pft .and. presc_cover ) then - - do no = 1,ns_o - pctlnd_o(no) = 100._r8 - pctnatveg_o(no) = pft_override%natveg - pctcrop_o(no) = pft_override%crop - end do - - ! otherewise if total cover isn't prescribed read it from the datasets - else - - ! Compute pctlnd_o, pctpft_o - - call gridmap_mapread(tgridmap, mapfname) - - ! Error checks for domain and map consistencies - - call domain_checksame( tdomain, ldomain, tgridmap ) - - ! Obtain frac_dst - call gridmap_calc_frac_dst(tgridmap, tdomain%mask, frac_dst) - ! Area-average percent cover on input grid [pctpft_i] to output grid - ! [pctpft_o] and correct [pctpft_o] according to land landmask - ! Note that percent cover is in terms of total grid area. - pctlnd_o(:) = frac_dst(:) * 100._r8 - - ! New format with extra variables on input - call gridmap_areaave_srcmask(tgridmap, pctnatveg_i, pctnatveg_o, nodata=0._r8, mask_src=tdomain%mask, frac_dst=frac_dst) - call gridmap_areaave_srcmask(tgridmap, pctcrop_i, pctcrop_o, nodata=0._r8, mask_src=tdomain%mask, frac_dst=frac_dst) - - ! - ! If specific PFT/CFT's are NOT prescribed set them from the input file - ! - if ( .not. use_input_pft )then - do m = 0, num_natpft - call gridmap_areaave_scs(tgridmap, pct_nat_pft_i(:,m), & - pct_nat_pft_o(:,m), nodata=0._r8, & - src_wt=pctnatveg_i*0.01_r8*tdomain%mask, & - dst_wt=pctnatveg_o*0.01_r8, frac_dst=frac_dst) - do no = 1,ns_o - if (pctlnd_o(no) < 1.0e-6 .or. pctnatveg_o(no) < 1.0e-6) then - if (m == 0) then - pct_nat_pft_o(no,m) = 100._r8 - else - pct_nat_pft_o(no,m) = 0._r8 - endif - end if - enddo - end do - do m = 1, num_cft - call gridmap_areaave_scs(tgridmap, pct_cft_i(:,m), pct_cft_o(:,m), & - nodata=0._r8, src_wt=pctcrop_i*0.01_r8*tdomain%mask, & - dst_wt=pctcrop_o*0.01_r8, frac_dst=frac_dst) - do no = 1,ns_o - if (pctlnd_o(no) < 1.0e-6 .or. pctcrop_o(no) < 1.0e-6) then - if (m == 1) then - pct_cft_o(no,m) = 100._r8 - else - pct_cft_o(no,m) = 0._r8 - endif - end if - enddo - end do - ! Otherwise do some error checking to make sure specific veg types are given where nat-veg and crop is assigned - else - do no = 1,ns_o - if (pctlnd_o(no) > 1.0e-6 .and. pctnatveg_o(no) > 1.0e-6) then - if ( pft_override%natveg <= 0.0_r8 )then - write(6,*) subname//': ERROR: no natural vegetation PFTs are being prescribed but there are natural '// & - 'vegetation areas: provide at least one natural veg PFT' - call abort() - return - end if - end if - if (pctlnd_o(no) > 1.0e-6 .and. pctcrop_o(no) > 1.0e-6) then - if ( pft_override%crop <= 0.0_r8 )then - write(6,*) subname//': ERROR: no crop CFTs are being prescribed but there are crop areas: provide at least one CFT' - call abort() - return - end if - end if - end do - end if - end if - - ! - ! If specific PFT/CFT's are prescribed set them directly - ! - if ( use_input_pft )then - do no = 1,ns_o - if (pctlnd_o(no) > 1.0e-6 .and. pctnatveg_o(no) > 1.0e-6) then - pct_nat_pft_o(no,noveg:num_natpft) = pft_override%natpft(noveg:num_natpft) - else - pct_nat_pft_o(no,noveg) = 100._r8 - pct_nat_pft_o(no,noveg+1:) = 0._r8 - end if - if (pctlnd_o(no) > 1.0e-6 .and. pctcrop_o(no) > 1.0e-6) then - pct_cft_o(no,1:num_cft) = pft_override%cft(1:num_cft) - else - pct_cft_o(no,1) = 100._r8 - pct_cft_o(no,2:) = 0._r8 - end if - pctpft_o(no,natpft_lb:natpft_ub) = pct_nat_pft_o(no,0:num_natpft) - pctpft_o(no,cft_lb:cft_ub) = pct_cft_o(no,1:num_cft) - end do - end if - - - ! Error check: percents should sum to 100 for land grid cells, within roundoff - ! Also correct sums so that if they differ slightly from 100, they are corrected to - ! equal 100 more exactly. - - do no = 1,ns_o - wst_sum = 0. - do m = 0, num_natpft - wst_sum = wst_sum + pct_nat_pft_o(no,m) - enddo - if (abs(wst_sum-100._r8) > relerr) then - write (6,*) subname//'error: nat pft = ', & - (pct_nat_pft_o(no,m), m = 0, num_natpft), & - ' do not sum to 100. at no = ',no,' but to ', wst_sum - call abort() - end if - - ! Correct sum so that if it differs slightly from 100, it is corrected to equal - ! 100 more exactly - do m = 1, num_natpft - pct_nat_pft_o(no,m) = pct_nat_pft_o(no,m) * 100._r8 / wst_sum - end do - - wst_sum = 0. - do m = 1, num_cft - wst_sum = wst_sum + pct_cft_o(no,m) - enddo - if (abs(wst_sum-100._r8) > relerr) then - write (6,*) subname//'error: crop cft = ', & - (pct_cft_o(no,m), m = 1, num_cft), & - ' do not sum to 100. at no = ',no,' but to ', wst_sum - call abort() - end if - - ! Correct sum so that if it differs slightly from 100, it is corrected to equal - ! 100 more exactly - do m = 1, num_cft - pct_cft_o(no,m) = pct_cft_o(no,m) * 100._r8 / wst_sum - end do - - end do - - ! Convert % pft as % of grid cell to % pft on the landunit and % of landunit on the - ! grid cell - do no = 1,ns_o - pctnatpft_o(no) = pct_pft_type( pct_nat_pft_o(no,:), pctnatveg_o(no), first_pft_index=natpft_lb ) - pctcft_o(no) = pct_pft_type( pct_cft_o(no,:), pctcrop_o(no), first_pft_index=cft_lb ) - end do - - ! ----------------------------------------------------------------- - ! Error check - ! Compare global areas on input and output grids - ! Only when you aren't prescribing the vegetation coverage everywhere - ! If use_input_pft is set this will compare the global coverage of - ! the prescribed vegetation to the coverage of PFT/CFT's on the input - ! datasets. - ! ----------------------------------------------------------------- - - if ( .not. presc_cover ) then - - ! Convert to pctpft over grid if using new format - do ni = 1, ns_i - pctnatpft_i(ni) = pct_pft_type( pct_nat_pft_i(ni,:), pctnatveg_i(ni), first_pft_index=natpft_lb ) - pctcft_i(ni) = pct_pft_type( pct_cft_i(ni,:), pctcrop_i(ni), first_pft_index=cft_lb ) - end do - - do no = 1,ns_o - pctpft_o(no,natpft_lb:natpft_ub) = pctnatpft_o(no)%get_pct_p2g() - pctpft_o(no,cft_lb:cft_ub) = pctcft_o(no)%get_pct_p2g() - end do - allocate(gpft_i(0:numpft_i-1)) - allocate(gpft_o(0:numpft_i-1)) - - ! input grid - - gpft_i(:) = 0. - garea_i = 0. - do ni = 1,ns_i - garea_i = garea_i + tgridmap%area_src(ni)*re**2 - do m = 0, numpft_i - 1 - gpft_i(m) = gpft_i(m) + pctpft_i(ni,m)*tgridmap%area_src(ni)*& - tdomain%mask(ni)*re**2 - end do - end do - if ( allocated(pctpft_i) ) deallocate (pctpft_i) - - ! output grid - - gpft_o(:) = 0. - garea_o = 0. - do no = 1,ns_o - garea_o = garea_o + tgridmap%area_dst(no)*re**2 - do m = 0, numpft_i - 1 - gpft_o(m) = gpft_o(m) + pctpft_o(no,m)*tgridmap%area_dst(no)*& - frac_dst(no)*re**2 - end do - end do - - ! comparison - - write (ndiag,*) - write (ndiag,'(1x,70a1)') ('=',k=1,70) - write (ndiag,*) 'PFTs Output' - write (ndiag,'(1x,70a1)') ('=',k=1,70) - - write (ndiag,*) - write (ndiag,'(1x,70a1)') ('.',k=1,70) - write (ndiag,1001) -1001 format (1x,'plant type ',20x,' input grid area',' output grid area',/ & - 1x,33x,' 10**6 km**2',' 10**6 km**2') - write (ndiag,'(1x,70a1)') ('.',k=1,70) - write (ndiag,*) - do m = 0, numpft_i - 1 - write (ndiag,1002) veg(m), gpft_i(m)*1.e-06/100.,gpft_o(m)*1.e-06/100. - end do -1002 format (1x,a35,f16.3,f17.3) - call shr_sys_flush(ndiag) - - deallocate(gpft_i, gpft_o, frac_dst) - - end if - deallocate( pctnatpft_i ) - deallocate( pctcft_i ) - deallocate(pctpft_o) - - - ! Deallocate dynamic memory - - deallocate(pctnatveg_i) - deallocate(pctnatveg_o) - deallocate(pctcrop_i) - deallocate(pctcrop_o) - deallocate(pct_cft_i) - deallocate(pct_cft_o) - deallocate(pct_nat_pft_i) - deallocate(pct_nat_pft_o) - if ( .not. presc_cover ) then - call domain_clean(tdomain) - call gridmap_clean(tgridmap) - end if - - write (6,*) 'Successfully made PFTs' - write (6,*) - - -end subroutine mkpft - -!----------------------------------------------------------------------- - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: mkpft_parse_oride -! -! !INTERFACE: -subroutine mkpft_parse_oride( string ) -! -! !DESCRIPTION: -! Parse the string with pft fraction and index information on it, to override -! the file with this information rather than reading from a file. -! -! !USES: - use shr_string_mod, only: shr_string_betweenTags, shr_string_countChar -! !ARGUMENTS: - character(len=256), intent(IN) :: string ! String to parse with PFT fraction - ! and index data -! -! !CALLED FROM: -! subroutine mksrfdat in module mksrfdatMod -! -! !REVISION HISTORY: -! Author: Erik Kluzek -! -! -! !LOCAL VARIABLES: -!EOP - integer :: rc ! error return code - integer :: num_elms ! number of elements - character(len=256) :: substring ! string between tags - character(len=*), parameter :: frc_start = "" - character(len=*), parameter :: frc_end = "" - character(len=*), parameter :: idx_start = "" - character(len=*), parameter :: idx_end = "" - character(len=*), parameter :: subname = 'mkpft_parse_oride' - !----------------------------------------------------------------------- - - ! NOTE(bja, 2015-02) pft_frc and pft_index can be reset multiple - ! times by calls to this function. If the number of elements being - ! set is different each time, then we are working with out of date - ! information, and the sums may not sum to 100%. - pft_frc = 0.0_r8 - pft_idx = -1 - - call shr_string_betweenTags( string, frc_start, frc_end, substring, rc ) - if ( rc /= 0 )then - write(6,*) subname//'Trouble finding pft_frac start end tags' - call abort() - return - end if - num_elms = shr_string_countChar( substring, ",", rc ) - read(substring,*) pft_frc(0:num_elms) - call shr_string_betweenTags( string, idx_start, idx_end, substring, rc ) - if ( rc /= 0 )then - write(6,*) subname//'Trouble finding pft_index start end tags' - call abort() - return - end if - if ( num_elms /= shr_string_countChar( substring, ",", rc ) )then - write(6,*) subname//'number of elements different between frc and idx fields' - call abort() - return - end if - read(substring,*) pft_idx(0:num_elms) -!----------------------------------------------------------------------- - -end subroutine mkpft_parse_oride - -!----------------------------------------------------------------------- - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: mkpft_check_oride -! -! !INTERFACE: -subroutine mkpft_check_oride( error_happened ) -! -! !DESCRIPTION: -! Check that the pft override values are valid -! !USES: - implicit none -! !ARGUMENTS: - logical, intent(out) :: error_happened ! Result, true if there was a problem -! -! !REVISION HISTORY: -! Author: Erik Kluzek -! -! -! !LOCAL VARIABLES: -!EOP - integer :: i, j ! indices - real(r8) :: sumpft ! Sum of pft_frc - real(r8), parameter :: hndrd = 100.0_r8 ! A hundred percent - character(len=32) :: subname = 'mkpftMod::mkpft_check_oride() ' -!----------------------------------------------------------------------- - - error_happened = .false. - sumpft = sum(pft_frc) - if ( sumpft == 0.0 )then - ! PFT fraction is NOT used - use_input_pft = .false. - else if ( abs(sumpft - hndrd) > 1.e-6 )then - write(6, '(a, a, f15.12)') trim(subname), 'Sum of PFT fraction is NOT equal to 100% =', sumpft - write(6,*) 'Set PFT fraction to : ', pft_frc(0:nzero) - write(6,*) 'With PFT index : ', pft_idx(0:nzero) - error_happened = .true. - call abort() - return - else - use_input_pft = .true. - nzero = numpft - do i = 0, numpft - if ( pft_frc(i) == 0.0_r8 )then - nzero = i-1 - exit - end if - end do - ! PFT fraction IS used, and sum is OK, now check details - do i = 0, nzero - if ( pft_frc(i) < 0.0_r8 .or. pft_frc(i) > hndrd )then - write(6,*) subname//'PFT fraction is out of range: pft_frc=', pft_frc(i) - error_happened = .true. - call abort() - return - else if ( pft_frc(i) > 0.0_r8 .and. pft_idx(i) == -1 )then - write(6,*) subname//'PFT fraction > zero, but index NOT set: pft_idx=', pft_idx(i) - error_happened = .true. - call abort() - return - end if - ! PFT index out of range - if ( pft_idx(i) < 0 .or. pft_idx(i) > numpft )then - write(6,*) subname//'PFT index is out of range: ', pft_idx(i) - error_happened = .true. - call abort() - return - end if - ! Make sure index values NOT used twice - do j = 0, i-1 - if ( pft_idx(i) == pft_idx(j) )then - write(6,*) subname//'Same PFT index is used twice: ', pft_idx(i) - error_happened = .true. - call abort() - return - end if - end do - end do - ! Make sure the rest of the fraction is zero and index are not set as well - do i = nzero+1, numpft - if ( pft_frc(i) /= 0.0_r8 .or. pft_idx(i) /= -1 )then - write(6,*) subname//'After PFT fraction is zeroed out, fraction is non zero, or index set' - error_happened = .true. - call abort() - return - end if - end do - end if - -end subroutine mkpft_check_oride - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: mkpftAtt -! -! !INTERFACE: -subroutine mkpftAtt( ncid, dynlanduse, xtype ) -! -! !DESCRIPTION: -! make PFT attributes on the output file -! - use mkncdio , only : check_ret, ncd_defvar, ncd_def_spatial_var - use fileutils , only : get_filename - use mkvarctl , only : mksrf_fvegtyp, mksrf_flai - use mkvarpar - -! !ARGUMENTS: - implicit none - include 'netcdf.inc' - integer, intent(in) :: ncid ! NetCDF file ID to write out to - logical, intent(in) :: dynlanduse ! if dynamic land-use file - integer, intent(in) :: xtype ! external type to output real data as -! -! !CALLED FROM: -! subroutine mkfile in module mkfileMod -! -! !REVISION HISTORY: -! Author: Erik Kluzek -! -! -! !LOCAL VARIABLES: -!EOP - integer :: pftsize ! size of lsmpft dimension - integer :: natpftsize ! size of natpft dimension - integer :: dimid ! input netCDF id's - character(len=256) :: str ! global attribute string - character(len=32) :: subname = 'mkpftAtt' - - ! Define dimensions - call check_ret(nf_def_dim (ncid, 'time' , nf_unlimited, dimid), subname) - - if (.not. dynlanduse) then - pftsize = numpft + 1 - call check_ret(nf_def_dim (ncid, 'lsmpft' , pftsize , dimid), subname) - end if - - natpftsize = num_natpft + 1 - call check_ret(nf_def_dim (ncid, 'natpft' , natpftsize , dimid), subname) - - ! zero-size dimensions can cause problems, so we only include the cft dimension if num_cft > 0 - ! Note that this implies that we can only include PCT_CFT on the dataset if num_cft > 0 - if (num_cft > 0) then - call check_ret(nf_def_dim (ncid, 'cft' , num_cft , dimid), subname) - end if - - ! Add global attributes - - if (.not. dynlanduse) then - str = get_filename(mksrf_flai) - call check_ret(nf_put_att_text(ncid, NF_GLOBAL, & - 'Lai_raw_data_file_name', len_trim(str), trim(str)), subname) - end if - - if ( use_input_pft ) then - str = 'TRUE' - call check_ret(nf_put_att_text (ncid, NF_GLOBAL, & - 'pft_override', len_trim(str), trim(str)), subname) - else - str = get_filename(mksrf_fvegtyp) - call check_ret(nf_put_att_text(ncid, NF_GLOBAL, & - 'Vegetation_type_raw_data_filename', len_trim(str), trim(str)), subname) - end if - - ! Define variables - - ! Coordinate variable for indices of natural PFTs - call ncd_defvar(ncid=ncid, varname='natpft', xtype=nf_int, & - dim1name='natpft', long_name='indices of natural PFTs', units='index') - - ! Coordinate variable for indices of CFTs - if (num_cft > 0) then - call ncd_defvar(ncid=ncid, varname='cft', xtype=nf_int, & - dim1name='cft', long_name='indices of CFTs', units='index') - end if - - call ncd_def_spatial_var(ncid=ncid, varname='LANDFRAC_PFT', xtype=nf_double, & - long_name='land fraction from pft dataset', units='unitless') - - call ncd_def_spatial_var(ncid=ncid, varname='PFTDATA_MASK', xtype=nf_int, & - long_name='land mask from pft dataset, indicative of real/fake points', units='unitless') - - if (.not. dynlanduse) then - call ncd_def_spatial_var(ncid=ncid, varname='PCT_NATVEG', xtype=xtype, & - long_name='total percent natural vegetation landunit', units='unitless') - end if - - ! PCT_CROP - if (.not. dynlanduse) then - call ncd_def_spatial_var(ncid=ncid, varname='PCT_CROP', xtype=xtype, & - long_name='total percent crop landunit', units='unitless') - else - call ncd_def_spatial_var(ncid=ncid, varname='PCT_CROP', xtype=xtype, & - lev1name='time', & - long_name='total percent crop landunit', units='unitless') - call ncd_def_spatial_var(ncid=ncid, varname='PCT_CROP_MAX', xtype=xtype, & - long_name='maximum total percent crop landunit during time period', units='unitless') - end if - - ! PCT_NAT_PFT - if (.not. dynlanduse) then - call ncd_def_spatial_var(ncid=ncid, varname='PCT_NAT_PFT', xtype=xtype, & - lev1name='natpft', & - long_name='percent plant functional type on the natural veg landunit (% of landunit)', units='unitless') - else - call ncd_def_spatial_var(ncid=ncid, varname='PCT_NAT_PFT', xtype=xtype, & - lev1name='natpft', lev2name='time', & - long_name='percent plant functional type on the natural veg landunit (% of landunit)', units='unitless') - call ncd_def_spatial_var(ncid=ncid, varname='PCT_NAT_PFT_MAX', xtype=xtype, & - lev1name='natpft', & - long_name='maximum percent plant functional type during time period (% of landunit)', units='unitless') - end if - - ! PCT_CFT - if (num_cft > 0) then - if (.not. dynlanduse) then - call ncd_def_spatial_var(ncid=ncid, varname='PCT_CFT', xtype=xtype, & - lev1name='cft', & - long_name='percent crop functional type on the crop landunit (% of landunit)', units='unitless') - else - call ncd_def_spatial_var(ncid=ncid, varname='PCT_CFT', xtype=xtype, & - lev1name='cft', lev2name='time', & - long_name='percent crop functional type on the crop landunit (% of landunit)', units='unitless') - call ncd_def_spatial_var(ncid=ncid, varname='PCT_CFT_MAX', xtype=xtype, & - lev1name='cft', & - long_name='maximum percent crop functional type during time period (% of landunit)', units='unitless') - end if - end if - - ! LAI,SAI,HTOP,HBOT - if (.not. dynlanduse) then - call ncd_def_spatial_var(ncid=ncid, varname='MONTHLY_LAI', xtype=xtype, & - lev1name='lsmpft', lev2name='time', & - long_name='monthly leaf area index', units='unitless') - - call ncd_def_spatial_var(ncid=ncid, varname='MONTHLY_SAI', xtype=xtype, & - lev1name='lsmpft', lev2name='time', & - long_name='monthly stem area index', units='unitless') - - call ncd_def_spatial_var(ncid=ncid, varname='MONTHLY_HEIGHT_TOP', xtype=xtype, & - lev1name='lsmpft', lev2name='time', & - long_name='monthly height top', units='meters') - - call ncd_def_spatial_var(ncid=ncid, varname='MONTHLY_HEIGHT_BOT', xtype=xtype, & - lev1name='lsmpft', lev2name='time', & - long_name='monthly height bottom', units='meters') - end if - - ! OTHER - if (dynlanduse) then - call ncd_defvar(ncid=ncid, varname='YEAR', xtype=nf_int, & - dim1name='time', & - long_name='Year of PFT data', units='unitless') - call ncd_defvar(ncid=ncid, varname='time', xtype=nf_int, & - dim1name='time', & - long_name='year', units='unitless') - call ncd_defvar(ncid=ncid, varname='input_pftdata_filename', xtype=nf_char, & - dim1name='nchar', & - dim2name='time', & - long_name='Input filepath for PFT values for this year', units='unitless') - else - call ncd_defvar(ncid=ncid, varname='time', xtype=nf_int, & - dim1name='time', & - long_name='Calendar month', units='month') - end if - -end subroutine mkpftAtt - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: constructor -! -! !INTERFACE: -function constructor( ) result(this) -! -! !DESCRIPTION: -! Construct a new PFT override object -! -! !ARGUMENTS: - implicit none - type(pft_oride) :: this -!EOP - character(len=32) :: subname = 'mkpftMod::constructor() ' - - this%crop = -1.0_r8 - this%natveg = -1.0_r8 - if ( num_natpft < 0 )then - write(6,*) subname//'num_natpft is NOT set = ', num_natpft - call abort() - return - end if - if ( num_cft < 0 )then - write(6,*) subname//'num_cft is NOT set = ', num_cft - call abort() - return - end if - allocate( this%natpft(noveg:num_natpft) ) - allocate( this%cft(1:num_cft) ) - this%natpft(:) = -1.0_r8 - this%cft(:) = -1.0_r8 - call this%InitZeroOut() -end function constructor - - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: InitZeroOut -! -! !INTERFACE: -subroutine InitZeroOut( this ) -! -! !DESCRIPTION: -! Initialize a pft_oride object with vegetation that's zeroed out -! -! !ARGUMENTS: - implicit none - class(pft_oride), intent(inout) :: this -!EOP - this%crop = 0.0_r8 - this%natveg = 0.0_r8 - - this%natpft = 0.0_r8 - this%natpft(noveg) = 100.0_r8 - this%cft = 0.0_r8 - this%cft(1) = 100.0_r8 -end subroutine InitZeroOut - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: InitZeroOut -! -! !INTERFACE: -subroutine InitAllPFTIndex( this ) -! -! !DESCRIPTION: -! Initialize a pft_oride object with vegetation that's zeroed out -! -! !ARGUMENTS: - implicit none - class(pft_oride), intent(inout) :: this -!EOP - integer :: m, i ! Indices - real(r8) :: croptot ! Total of crop - real(r8) :: natvegtot ! Total of natural vegetation - character(len=32) :: subname = 'mkpftMod::coInitAllPFTIndex() ' - - croptot = 0.0_r8 - natvegtot = 0.0_r8 - this%natpft = 0.0_r8 - this%cft = 0.0_r8 - do m = noveg, nzero - i = pft_idx(m) - if ( (i < noveg) .or. (i > numpft) )then - write(6,*) subname//'PFT index is out of valid range' - call abort() - return - else if ( i <= num_natpft )then - this%natpft(i) = pft_frc(m) - natvegtot = natvegtot + pft_frc(m) - else - this%cft(i-num_natpft) = pft_frc(m) - croptot = croptot + pft_frc(m) - end if - end do - this%crop = croptot - this%natveg = natvegtot - ! Renormalize - if ( natvegtot > 0.0_r8 )then - this%natpft = 100.0_r8 * this%natpft / natvegtot - else - this%natpft(noveg) = 100.0_r8 - end if - if (croptot > 0.0_r8 )then - this%cft = 100.0_r8 * this%cft / croptot - else - this%cft(1) = 100.0_r8 - end if - -end subroutine InitAllPFTIndex - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: clean -! -! !INTERFACE: -subroutine Clean( this ) -! -! !DESCRIPTION: -! Clean up a PFT Oride object -! -! !ARGUMENTS: - implicit none - class(pft_oride), intent(inout) :: this -!EOP - this%crop = -1.0_r8 - this%natveg = -1.0_r8 - deallocate( this%natpft ) - deallocate( this%cft ) - -end subroutine Clean - -!----------------------------------------------------------------------- - -end module mkpftMod diff --git a/tools/mksurfdata_map/src/mksoilMod.F90 b/tools/mksurfdata_map/src/mksoilMod.F90 deleted file mode 100644 index d7cad23e0d..0000000000 --- a/tools/mksurfdata_map/src/mksoilMod.F90 +++ /dev/null @@ -1,1237 +0,0 @@ -module mksoilMod -!----------------------------------------------------------------------- -!BOP -! -! !MODULE: mksoilMod -! -! !DESCRIPTION: -! Make soil data (texture, color and organic) -! -! !REVISION HISTORY: -! Author: Erik Kluzek -! -!----------------------------------------------------------------------- -!!USES: - use shr_kind_mod, only : r8 => shr_kind_r8, r4=>shr_kind_r4 - use shr_sys_mod , only : shr_sys_flush - use mkdomainMod , only : domain_checksame - use mksoilUtilsMod, only : mkrank, dominant_soil_color - implicit none - - SAVE - private ! By default make data private -! -! !PUBLIC MEMBER FUNCTIONS: -! - public mksoilInit ! Soil Initialization - - public mksoilAtt ! Add attributes to output file - - public mksoiltex ! Set soil texture - public mkorganic ! Set organic soil - public mksoilcol ! Set soil color - public mkfmax ! Make percent fmax -! -! !PUBLIC DATA MEMBERS: -! - real(r8), public, parameter :: unset = -999.99_r8 ! Flag to signify soil texture override not set - real(r8), public :: soil_sand = unset ! soil texture sand % to override with - real(r8), public :: soil_clay = unset ! soil texture clay % to override with - real(r8), public :: soil_fmax = unset ! soil max saturation frac to override with - integer , parameter :: unsetcol = -999 ! flag to indicate soil color NOT set - integer , public :: soil_color= unsetcol ! soil color to override with -! -! !PRIVATE DATA MEMBERS: -! -! !PRIVATE MEMBER FUNCTIONS: - private :: mksoiltexInit ! Soil texture Initialization - private :: mksoilcolInit ! Soil color Initialization - private :: mksoilfmaxInit ! Soil fmax Initialization - -!EOP -!=============================================================== -contains -!=============================================================== - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: mksoilInit -! -! !INTERFACE: -subroutine mksoilInit( ) -! -! !DESCRIPTION: -! Initialize the different soil types -! !USES: -! -! !ARGUMENTS: - implicit none -! -! !REVISION HISTORY: -! Author: Erik Kluzek -! -! -! !LOCAL VARIABLES: -!EOP - character(len=32) :: subname = 'mksoilInit' -!----------------------------------------------------------------------- - call mksoiltexInit() - call mksoilcolInit() - call mksoilfmaxInit() - -end subroutine mksoilInit - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: mksoiltexInit -! -! !INTERFACE: -subroutine mksoiltexInit( ) -! -! !DESCRIPTION: -! Initialize of make soil texture -! !USES: -! -! !ARGUMENTS: - implicit none -! -! !REVISION HISTORY: -! Author: Erik Kluzek -! -! -! !LOCAL VARIABLES: -!EOP - real(r8) :: sumtex - character(len=32) :: subname = 'mksoiltexInit' -!----------------------------------------------------------------------- - if ( soil_clay /= unset )then - write(6,*) 'Replace soil clay % for all points with: ', soil_clay - if ( soil_sand == unset )then - write (6,*) subname//':error: soil_clay set, but NOT soil_sand' - call abort() - end if - end if - if ( soil_sand /= unset )then - write(6,*) 'Replace soil sand % for all points with: ', soil_sand - if ( soil_clay == unset )then - write (6,*) subname//':error: soil_sand set, but NOT soil_clay' - call abort() - end if - sumtex = soil_sand + soil_clay - if ( sumtex < 0.0_r8 .or. sumtex > 100.0_r8 )then - write (6,*) subname//':error: soil_sand and soil_clay out of bounds: sand, clay = ', & - soil_sand, soil_clay - call abort() - end if - end if - -end subroutine mksoiltexInit - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: mksoiltex -! -! !INTERFACE: -subroutine mksoiltex(ldomain, mapfname, datfname, ndiag, sand_o, clay_o) -! -! !DESCRIPTION: -! make %sand and %clay from IGBP soil data, which includes -! igbp soil 'mapunits' and their corresponding textures -! -! !USES: - use mkdomainMod, only : domain_type, domain_clean, domain_read - use mkgridmapMod - use mkvarpar - use mkvarctl - use mkncdio -! -! !ARGUMENTS: - implicit none - type(domain_type), intent(in) :: ldomain - character(len=*) , intent(in) :: mapfname ! input mapping file name - character(len=*) , intent(in) :: datfname ! input data file name - integer , intent(in) :: ndiag ! unit number for diag out - real(r8) , intent(out):: sand_o(:,:) ! % sand (output grid) - real(r8) , intent(out):: clay_o(:,:) ! % clay (output grid) -! -! !CALLED FROM: -! subroutine mksrfdat in module mksrfdatMod -! -! !REVISION HISTORY: -! Author: Mariana Vertenstein -! -! -! !LOCAL VARIABLES: -!EOP - type(gridmap_type) :: tgridmap - type(domain_type) :: tdomain ! local domain - character(len=38) :: typ ! soil texture based on ... - integer :: nlay ! number of soil layers - integer :: mapunitmax ! max value of igbp soil mapunits - integer :: mapunittemp ! temporary igbp soil mapunit - integer :: maxovr - integer , allocatable :: novr(:) - integer , allocatable :: kmap(:,:) - real(r8), allocatable :: kwgt(:,:) - integer , allocatable :: kmax(:) - real(r8), allocatable :: wst(:) - real(r8), allocatable :: sand_i(:,:) ! input grid: percent sand - real(r8), allocatable :: clay_i(:,:) ! input grid: percent clay - real(r8), allocatable :: mapunit_i(:) ! input grid: igbp soil mapunits - real(r8), allocatable :: frac_dst(:) ! output fractions - real(r8), allocatable :: mask_r8(:) ! float of tdomain%mask - integer, parameter :: num=2 ! set soil mapunit number - integer :: wsti(num) ! index to 1st and 2nd largest wst - integer, parameter :: nlsm=4 ! number of soil textures - character(len=38) :: soil(0:nlsm) ! name of each soil texture - real(r8) :: gast_i(0:nlsm) ! global area, by texture type - real(r8) :: gast_o(0:nlsm) ! global area, by texture type - real(r8) :: wt ! map overlap weight - real(r8) :: sum_fldi ! global sum of dummy input fld - real(r8) :: sum_fldo ! global sum of dummy output fld - integer :: l,k,n,m,ni,no,ns_i,ns_o ! indices - integer :: k1,k2 ! indices - integer :: ncid,dimid,varid ! input netCDF id's - integer :: ier ! error status - integer :: miss = 99999 ! missing data indicator - real(r8) :: relerr = 0.00001 ! max error: sum overlap wts ne 1 - logical :: found ! temporary - integer :: kmap_max ! maximum overlap weights - integer, parameter :: kmap_max_min = 90 ! kmap_max mininum value - integer, parameter :: km_mx_ns_prod = 160000 ! product of kmap_max*ns_o to keep constant - character(len=32) :: subname = 'mksoiltex' -!----------------------------------------------------------------------- - - write (6,*) 'Attempting to make %sand and %clay .....' - call shr_sys_flush(6) - - ! ----------------------------------------------------------------- - ! Define the model surface types: 0 to nlsm - ! ----------------------------------------------------------------- - - soil(0) = 'no soil: ocean, glacier, lake, no data' - soil(1) = 'clays ' - soil(2) = 'sands ' - soil(3) = 'loams ' - soil(4) = 'silts ' - - ! ----------------------------------------------------------------- - ! Read input file - ! ----------------------------------------------------------------- - - ! Obtain input grid info, read local fields - - call domain_read(tdomain,datfname) - ns_i = tdomain%ns - ns_o = ldomain%ns - - write (6,*) 'Open soil texture file: ', trim(datfname) - call check_ret(nf_open(datfname, 0, ncid), subname) - call check_ret(nf_inq_dimid (ncid, 'number_of_layers', dimid), subname) - call check_ret(nf_inq_dimlen (ncid, dimid, nlay), subname) - - call check_ret(nf_inq_dimid (ncid, 'max_value_mapunit', dimid), subname) - call check_ret(nf_inq_dimlen (ncid, dimid, mapunitmax), subname) - - allocate(sand_i(mapunitmax,nlay), & - clay_i(mapunitmax,nlay), & - mapunit_i(ns_i), stat=ier) - if (ier/=0) call abort() - - call check_ret(nf_inq_varid (ncid, 'MAPUNITS', varid), subname) - call check_ret(nf_get_var_double (ncid, varid, mapunit_i), subname) - - call check_ret(nf_inq_varid (ncid, 'PCT_SAND', varid), subname) - call check_ret(nf_get_var_double (ncid, varid, sand_i), subname) - - call check_ret(nf_inq_varid (ncid, 'PCT_CLAY', varid), subname) - call check_ret(nf_get_var_double (ncid, varid, clay_i), subname) - - call check_ret(nf_close(ncid), subname) - - ! Compute local fields _o - if (soil_sand==unset .and. soil_clay==unset) then - - call gridmap_mapread(tgridmap, mapfname) - - ! Error checks for domain and map consistencies - - call domain_checksame( tdomain, ldomain, tgridmap ) - - ! Obtain frac_dst - allocate(frac_dst(ns_o), stat=ier) - if (ier/=0) call abort() - call gridmap_calc_frac_dst(tgridmap, tdomain%mask, frac_dst) - - ! kmap_max are the maximum number of mapunits that will consider on - ! any output gridcell - this is set currently above and can be changed - ! kmap(:) are the mapunit values on the input grid - ! kwgt(:) are the weights on the input grid - - allocate(novr(ns_o)) - novr(:) = 0 - do n = 1,tgridmap%ns - ni = tgridmap%src_indx(n) - if (tdomain%mask(ni) > 0) then - no = tgridmap%dst_indx(n) - novr(no) = novr(no) + 1 - end if - end do - maxovr = maxval(novr(:)) - kmap_max = min(maxovr,max(kmap_max_min,km_mx_ns_prod/ns_o)) - deallocate(novr) - - write(6,*)'kmap_max= ',kmap_max,' maxovr= ',maxovr,' ns_o= ',ns_o,' size= ',(kmap_max+1)*ns_o - - allocate(kmap(0:kmap_max,ns_o), stat=ier) - if (ier/=0) call abort() - allocate(kwgt(0:kmap_max,ns_o), stat=ier) - if (ier/=0) call abort() - allocate(kmax(ns_o), stat=ier) - if (ier/=0) call abort() - allocate(wst(0:kmap_max), stat=ier) - if (ier/=0) call abort() - - kwgt(:,:) = 0. - kmap(:,:) = 0 - kmax(:) = 0 - - do n = 1,tgridmap%ns - ni = tgridmap%src_indx(n) - no = tgridmap%dst_indx(n) - wt = tgridmap%wovr(n) * tdomain%mask(ni) - if (wt > 0._r8) then - k = mapunit_i(ni) - found = .false. - do l = 0,kmax(no) - if (k == kmap(l,no)) then - kwgt(l,no) = kwgt(l,no) + wt - found = .true. - exit - end if - end do - if (.not. found) then - kmax(no) = kmax(no) + 1 - if (kmax(no) > kmap_max) then - write(6,*)'kmax is > kmap_max= ',kmax(no), 'kmap_max = ', & - kmap_max,' for no = ',no - write(6,*)'reset kmap_max in mksoilMod to a greater value' - call abort() - end if - kmap(kmax(no),no) = k - kwgt(kmax(no),no) = wt - end if - end if - enddo - - end if - - do no = 1,ns_o - - if (soil_sand==unset .and. soil_clay==unset) then - wst(:) = 0. - wst(0:kmax(no)) = kwgt(0:kmax(no),no) - - ! Rank non-zero weights by soil mapunit. - ! k1 is the most extensive mapunit. - ! k2 is the second most extensive mapunit. - - if (maxval(wst(:)) > 0) then - call mkrank (kmax(no)+1, wst(0:kmax(no)), miss, wsti, num) - k1 = kmap(wsti(1),no) - if (wsti(2) == miss) then - k2 = miss - else - k2 = kmap(wsti(2),no) - end if - else - k1 = 0 - k2 = 0 - end if - - end if - - ! Set soil texture as follows: - ! a. Use dominant igbp soil mapunit based on area of overlap unless - ! 'no data' is dominant - ! b. In this case use second most dominant mapunit if it has data - ! c. If this has no data or if there isn't a second most dominant - ! mapunit, use loam for soil texture - - if (soil_sand/=unset .and. soil_clay/=unset) then !---soil texture is input - do l = 1, nlay - sand_o(no,l) = soil_sand - clay_o(no,l) = soil_clay - end do - else if (k1 /= 0) then !---not 'no data' - do l = 1, nlay - sand_o(no,l) = sand_i(k1,l) - clay_o(no,l) = clay_i(k1,l) - end do - else !---if (k1 == 0) then - if (k2 == 0 .or. k2 == miss) then !---no data - do l = 1, nlay - sand_o(no,l) = 43. !---use loam - clay_o(no,l) = 18. - end do - else !---if (k2 /= 0 and /= miss) - do l = 1, nlay - sand_o(no,l) = sand_i(k2,l) - clay_o(no,l) = clay_i(k2,l) - end do - end if !---end of k2 if-block - end if !---end of k1 if-block - - enddo - - if (soil_sand==unset .and. soil_clay==unset) then - - ! Global sum of output field - - allocate(mask_r8(ns_i), stat=ier) - if (ier/=0) call abort() - mask_r8 = tdomain%mask - call gridmap_check( tgridmap, mask_r8, frac_dst, subname ) - - ! ----------------------------------------------------------------- - ! Error check2 - ! Compare global area of each soil type on input and output grids - ! ----------------------------------------------------------------- - - ! input grid: global areas by texture class - - gast_i(:) = 0. - do l = 1, nlay - do ni = 1,ns_i - mapunittemp = nint(mapunit_i(ni)) - if (mapunittemp==0) then - typ = 'no soil: ocean, glacier, lake, no data' - else if (clay_i(mapunittemp,l) >= 40.) then - typ = 'clays' - else if (sand_i(mapunittemp,l) >= 50.) then - typ = 'sands' - else if (clay_i(mapunittemp,l)+sand_i(mapunittemp,l) < 50.) then - if (tdomain%mask(ni) /= 0.) then - typ = 'silts' - else !if (tdomain%mask(ni) == 0.) then no data - typ = 'no soil: ocean, glacier, lake, no data' - end if - else - typ = 'loams' - end if - do m = 0, nlsm - if (typ == soil(m)) go to 101 - end do - write (6,*) 'MKSOILTEX error: sand = ',sand_i(mapunittemp,l), & - ' clay = ',clay_i(mapunittemp,l), & - ' not assigned to soil type for input grid lon,lat,layer = ',ni,l - call abort() -101 continue - gast_i(m) = gast_i(m) + tgridmap%area_src(ni)*tdomain%mask(ni)*re**2 - end do - end do - - ! output grid: global areas by texture class - - gast_o(:) = 0. - do l = 1, nlay - do no = 1,ns_o - if (clay_o(no,l)==0. .and. sand_o(no,l)==0.) then - typ = 'no soil: ocean, glacier, lake, no data' - else if (clay_o(no,l) >= 40.) then - typ = 'clays' - else if (sand_o(no,l) >= 50.) then - typ = 'sands' - else if (clay_o(no,l)+sand_o(no,l) < 50.) then - typ = 'silts' - else - typ = 'loams' - end if - do m = 0, nlsm - if (typ == soil(m)) go to 102 - end do - write (6,*) 'MKSOILTEX error: sand = ',sand_o(no,l), & - ' clay = ',clay_o(no,l), & - ' not assigned to soil type for output grid lon,lat,layer = ',no,l - call abort() -102 continue - gast_o(m) = gast_o(m) + tgridmap%area_dst(no)*frac_dst(no)*re**2 - end do - end do - - ! Diagnostic output - - write (ndiag,*) - write (ndiag,'(1x,70a1)') ('=',l=1,70) - write (ndiag,*) 'Soil Texture Output' - write (ndiag,'(1x,70a1)') ('=',l=1,70) - write (ndiag,*) - - write (ndiag,*) 'The following table of soil texture classes is for comparison only.' - write (ndiag,*) 'The actual data is continuous %sand, %silt and %clay not textural classes' - write (ndiag,*) - - write (ndiag,*) - write (ndiag,'(1x,70a1)') ('.',l=1,70) - write (ndiag,1001) -1001 format (1x,'soil texture class',17x,' input grid area output grid area',/ & - 1x,33x,' 10**6 km**2',' 10**6 km**2') - write (ndiag,'(1x,70a1)') ('.',l=1,70) - write (ndiag,*) - - do l = 0, nlsm - write (ndiag,1002) soil(l),gast_i(l)*1.e-6,gast_o(l)*1.e-6 -1002 format (1x,a38,f16.3,f17.3) - end do - - end if - - ! Deallocate dynamic memory - - call domain_clean(tdomain) - if (soil_sand==unset .and. soil_clay==unset) then - call gridmap_clean(tgridmap) - deallocate (kmap, kwgt, kmax, wst) - deallocate (sand_i,clay_i,mapunit_i) - deallocate (frac_dst) - deallocate (mask_r8) - end if - - - write (6,*) 'Successfully made %sand and %clay' - write (6,*) - call shr_sys_flush(6) - -end subroutine mksoiltex - -!----------------------------------------------------------------------- - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: mksoilcolInit -! -! !INTERFACE: -subroutine mksoilcolInit( ) -! -! !DESCRIPTION: -! Initialize of make soil color -! !USES: -! -! !ARGUMENTS: - implicit none -! -! !REVISION HISTORY: -! Author: Erik Kluzek -! -! -! !LOCAL VARIABLES: -!EOP - real(r8) :: sumtex - character(len=32) :: subname = 'mksoilcolInit' -!----------------------------------------------------------------------- - - ! Error check soil_color if it is set - if ( soil_color /= unsetcol )then - if ( soil_color < 0 .or. soil_color > 20 )then - write(6,*)'soil_color is out of range = ', soil_color - call abort() - end if - write(6,*) 'Replace soil color for all points with: ', soil_color - end if -end subroutine mksoilcolInit - - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: mksoilcol -! -! !INTERFACE: -subroutine mksoilcol(ldomain, mapfname, datfname, ndiag, & - soil_color_o, nsoicol) -! -! !DESCRIPTION: -! make %sand and %clay from IGBP soil data, which includes -! igbp soil 'mapunits' and their corresponding textures -! -! !USES: - use mkdomainMod, only : domain_type, domain_clean, domain_read - use mkgridmapMod - use mkvarpar - use mkvarctl - use mkncdio -! -! !ARGUMENTS: - implicit none - type(domain_type), intent(in) :: ldomain - character(len=*) , intent(in) :: mapfname ! input mapping file name - character(len=*) , intent(in) :: datfname ! input data file name - integer , intent(in) :: ndiag ! unit number for diag out - integer , intent(out):: soil_color_o(:) ! soil color classes - integer , intent(out):: nsoicol ! number of soil colors -! -! !CALLED FROM: -! subroutine mksrfdat in module mksrfdatMod -! -! !REVISION HISTORY: -! Author: Mariana Vertenstein -! -! -! !LOCAL VARIABLES: -!EOP - type(gridmap_type) :: tgridmap - type(domain_type) :: tdomain ! local domain - real(r8), allocatable :: gast_i(:) ! global area, by surface type - real(r8), allocatable :: gast_o(:) ! global area, by surface type - integer , allocatable :: soil_color_i(:) ! input grid: BATS soil color - real(r8), allocatable :: frac_dst(:) ! output fractions - real(r8), allocatable :: mask_r8(:) ! float of tdomain%mask - real(r8) :: sum_fldi ! global sum of dummy input fld - real(r8) :: sum_fldo ! global sum of dummy output fld - character(len=35), allocatable :: col(:) ! name of each color - integer :: k,l,m,ni,no,ns_i,ns_o ! indices - integer :: ncid,dimid,varid ! input netCDF id's - integer :: ier ! error status - real(r8) :: relerr = 0.00001 ! max error: sum overlap wts ne 1 - character(len=32) :: subname = 'mksoilcol' -!----------------------------------------------------------------------- - - write (6,*) 'Attempting to make soil color classes .....' - call shr_sys_flush(6) - - ! ----------------------------------------------------------------- - ! Read input file - ! ----------------------------------------------------------------- - - ns_o = ldomain%ns - - ! Obtain input grid info, read local fields - - call domain_read(tdomain,datfname) - ns_i = tdomain%ns - allocate(soil_color_i(ns_i), stat=ier) - if (ier/=0) call abort() - allocate(frac_dst(ns_o), stat=ier) - if (ier/=0) call abort() - - write (6,*) 'Open soil color file: ', trim(datfname) - call check_ret(nf_open(datfname, 0, ncid), subname) - call check_ret(nf_inq_varid (ncid, 'SOIL_COLOR', varid), subname) - call check_ret(nf_get_var_int (ncid, varid, soil_color_i), subname) - call check_ret(nf_close(ncid), subname) - - nsoicol = maxval(soil_color_i) - write(6,*)'nsoicol = ',nsoicol - - allocate(gast_i(0:nsoicol),gast_o(0:nsoicol),col(0:nsoicol)) - - ! ----------------------------------------------------------------- - ! Define the model color classes: 0 to nsoicol - ! ----------------------------------------------------------------- - - if (nsoicol == 20) then - col(0) = 'no soil ' - col(1) = 'class 1: light ' - col(2) = 'class 2: ' - col(3) = 'class 3: ' - col(4) = 'class 4: ' - col(5) = 'class 5: ' - col(6) = 'class 6: ' - col(7) = 'class 7: ' - col(8) = 'class 8: ' - col(9) = 'class 9: ' - col(10) = 'class 10: ' - col(11) = 'class 11: ' - col(12) = 'class 12: ' - col(13) = 'class 13: ' - col(14) = 'class 14: ' - col(15) = 'class 15: ' - col(16) = 'class 16: ' - col(17) = 'class 17: ' - col(18) = 'class 18: ' - col(19) = 'class 19: ' - col(20) = 'class 20: dark ' - else if (nsoicol == 8) then - col(0) = 'no soil ' - col(1) = 'class 1: light ' - col(2) = 'class 2: ' - col(3) = 'class 3: ' - col(4) = 'class 4: ' - col(5) = 'class 5: ' - col(6) = 'class 6: ' - col(7) = 'class 7: ' - col(8) = 'class 8: dark ' - else - write(6,*)'nsoicol value of ',nsoicol,' is not currently supported' - call abort() - end if - - ! Error check soil_color if it is set - if ( soil_color /= unsetcol )then - if ( soil_color > nsoicol )then - write(6,*)'soil_color is out of range = ', soil_color - call abort() - end if - - do no = 1,ns_o - soil_color_o(no) = soil_color - end do - - else - - call gridmap_mapread(tgridmap, mapfname) - - ! Error checks for domain and map consistencies - - call domain_checksame( tdomain, ldomain, tgridmap ) - - ! Obtain frac_dst - call gridmap_calc_frac_dst(tgridmap, tdomain%mask, frac_dst) - - ! Determine dominant soil color for each output cell - - call dominant_soil_color( & - tgridmap = tgridmap, & - mask_i = tdomain%mask, & - soil_color_i = soil_color_i, & - nsoicol = nsoicol, & - soil_color_o = soil_color_o) - - ! Global sum of output field - - allocate(mask_r8(ns_i), stat=ier) - if (ier/=0) call abort() - mask_r8 = tdomain%mask - call gridmap_check( tgridmap, mask_r8, frac_dst, subname ) - - ! ----------------------------------------------------------------- - ! Error check2 - ! Compare global area of each soil color on input and output grids - ! ----------------------------------------------------------------- - - gast_i(:) = 0. - do ni = 1,ns_i - k = soil_color_i(ni) - gast_i(k) = gast_i(k) + tgridmap%area_src(ni)*tdomain%mask(ni)*re**2 - end do - - gast_o(:) = 0. - do no = 1,ns_o - k = soil_color_o(no) - gast_o(k) = gast_o(k) + tgridmap%area_dst(no)*frac_dst(no)*re**2 - end do - - ! area comparison - - write (ndiag,*) - write (ndiag,'(1x,70a1)') ('=',k=1,70) - write (ndiag,*) 'Soil Color Output' - write (ndiag,'(1x,70a1)') ('=',k=1,70) - - write (ndiag,*) - write (ndiag,'(1x,70a1)') ('.',k=1,70) - write (ndiag,1001) -1001 format (1x,'soil color type',20x,' input grid area output grid area',/ & - 1x,33x,' 10**6 km**2',' 10**6 km**2') - write (ndiag,'(1x,70a1)') ('.',k=1,70) - write (ndiag,*) - - do k = 0, nsoicol - write (ndiag,1002) col(k),gast_i(k)*1.e-6,gast_o(k)*1.e-6 -1002 format (1x,a35,f16.3,f17.3) - end do - - end if - - ! Deallocate dynamic memory - - call domain_clean(tdomain) - if ( soil_color == unsetcol )then - call gridmap_clean(tgridmap) - end if - deallocate (soil_color_i,gast_i,gast_o,col, frac_dst, mask_r8) - - write (6,*) 'Successfully made soil color classes' - write (6,*) - call shr_sys_flush(6) - -end subroutine mksoilcol - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: mkorganic -! -! !INTERFACE: -subroutine mkorganic(ldomain, mapfname, datfname, ndiag, organic_o) -! -! !DESCRIPTION: -! make organic matter dataset -! -! !USES: - use mkdomainMod, only : domain_type, domain_clean, domain_read - use mkgridmapMod - use mkvarpar - use mkvarctl - use mkncdio -! -! !ARGUMENTS: - implicit none - type(domain_type), intent(in) :: ldomain - character(len=*) , intent(in) :: mapfname ! input mapping file name - character(len=*) , intent(in) :: datfname ! input data file name - integer , intent(in) :: ndiag ! unit number for diag out - real(r8) , intent(out):: organic_o(:,:) ! output grid: -! -! !CALLED FROM: -! subroutine mksrfdat in module mksrfdatMod -! -! !REVISION HISTORY: -! -! Author: David Lawrence -! -! -! !LOCAL VARIABLES: -!EOP - type(gridmap_type) :: tgridmap - type(domain_type) :: tdomain ! local domain - real(r8), allocatable :: organic_i(:,:) ! input grid: total column organic matter - real(r8), allocatable :: frac_dst(:) ! output fractions - real(r8) :: sum_fldi ! global sum of dummy input fld - real(r8) :: sum_fldo ! global sum of dummy output fld - real(r8) :: gomlev_i ! input grid: global organic on lev - real(r8) :: garea_i ! input grid: global area - real(r8) :: gomlev_o ! output grid: global organic on lev - real(r8) :: garea_o ! output grid: global area - integer :: k,n,m,ni,no,ns_i ! indices - integer :: lev ! level index - integer :: nlay ! number of soil layers - integer :: ncid,dimid,varid ! input netCDF id's - integer :: ier ! error status - real(r8) :: relerr = 0.00001 ! max error: sum overlap wts ne 1 - character(len=32) :: subname = 'mkorganic' -!----------------------------------------------------------------------- - - write (6,*) 'Attempting to make organic matter dataset .....' - call shr_sys_flush(6) - - ! ----------------------------------------------------------------- - ! Read input file - ! ----------------------------------------------------------------- - - ! Obtain input grid info, read local fields - - call domain_read(tdomain,datfname) - ns_i = tdomain%ns - - write (6,*) 'Open soil organic file: ', trim(datfname) - call check_ret(nf_open(datfname, 0, ncid), subname) - - call check_ret(nf_inq_dimid (ncid, 'number_of_layers', dimid), subname) - call check_ret(nf_inq_dimlen (ncid, dimid, nlay), subname) - - allocate(organic_i(ns_i,nlay),stat=ier) - if (ier/=0) call abort() - allocate(frac_dst(ldomain%ns),stat=ier) - if (ier/=0) call abort() - - if (nlay /= nlevsoi) then - write(6,*)'nlay, nlevsoi= ',nlay,nlevsoi,' do not match' - call abort() - end if - - call check_ret(nf_inq_varid (ncid, 'ORGANIC', varid), subname) - call check_ret(nf_get_var_double (ncid, varid, organic_i), subname) - - call check_ret(nf_close(ncid), subname) - - ! Area-average percent cover on input grid to output grid - ! and correct according to land landmask - ! Note that percent cover is in terms of total grid area. - - call gridmap_mapread(tgridmap, mapfname ) - - call domain_checksame( tdomain, ldomain, tgridmap ) - - ! Obtain frac_dst - call gridmap_calc_frac_dst(tgridmap, tdomain%mask, frac_dst) - - do lev = 1,nlay - call gridmap_areaave_srcmask(tgridmap, organic_i(:,lev), organic_o(:,lev), nodata=0._r8, mask_src=tdomain%mask, frac_dst=frac_dst) - end do - - do lev = 1,nlevsoi - - ! Check for conservation - - do no = 1,ldomain%ns - if ((organic_o(no,lev)) > 130.000001_r8) then - write (6,*) 'MKORGANIC error: organic = ',organic_o(no,lev), & - ' greater than 130.000001 for column, row = ',no - call shr_sys_flush(6) - call abort() - end if - enddo - -! ! Diagnostic output - - ! TODO: there is nothing being written out here currently - all zeroes - ! So for now these are commented out -!!$ write (ndiag,*) -!!$ write (ndiag,'(1x,70a1)') ('.',k=1,70) -!!$ write (ndiag,2001) -!!$2001 format (1x,'surface type input grid area output grid area'/ & -!!$ 1x,' 10**6 km**2 10**6 km**2 ') -!!$ write (ndiag,'(1x,70a1)') ('.',k=1,70) -!!$ write (ndiag,*) -!!$ write (ndiag,2002) gomlev_i*1.e-06,gomlev_o*1.e-06 -!!$ write (ndiag,2004) garea_i*1.e-06,garea_o*1.e-06 -!!$2002 format (1x,'organic ',f14.3,f17.3) -!!$2004 format (1x,'all surface ',f14.3,f17.3) -!!$ - call shr_sys_flush(ndiag) - - write (6,*) 'Successfully made organic matter, level = ', lev - call shr_sys_flush(6) - - end do ! lev - - ! Deallocate dynamic memory - - call domain_clean(tdomain) - call gridmap_clean(tgridmap) - deallocate (organic_i) - deallocate (frac_dst) - - write (6,*) 'Successfully made organic matter' - call shr_sys_flush(6) - write(6,*) - -end subroutine mkorganic - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: mksoilfmaxInit -! -! !INTERFACE: -subroutine mksoilfmaxInit( ) -! -! !DESCRIPTION: -! Initialize of make soil fmax -! !USES: -! -! !ARGUMENTS: - implicit none -! -! !REVISION HISTORY: -! Author: Erik Kluzek -! -! -! !LOCAL VARIABLES: -!EOP - real(r8) :: sumtex - character(len=32) :: subname = 'mksoilfmaxInit' -!----------------------------------------------------------------------- - - ! Error check soil_fmax if it is set - if ( soil_fmax /= unset )then - if ( soil_fmax < 0.0 .or. soil_fmax > 1.0 )then - write(6,*)'soil_fmax is out of range = ', soil_fmax - call abort() - end if - write(6,*) 'Replace soil fmax for all points with: ', soil_fmax - end if - -end subroutine mksoilfmaxInit - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: mkfmax -! -! !INTERFACE: -subroutine mkfmax(ldomain, mapfname, datfname, ndiag, fmax_o) -! -! !DESCRIPTION: -! make percent fmax -! -! !USES: - use mkdomainMod, only : domain_type, domain_clean, domain_read - use mkgridmapMod - use mkvarpar - use mkvarctl - use mkncdio -! -! !ARGUMENTS: - implicit none - type(domain_type), intent(in) :: ldomain - character(len=*) , intent(in) :: mapfname ! input mapping file name - character(len=*) , intent(in) :: datfname ! input data file name - integer , intent(in) :: ndiag ! unit number for diag out - real(r8) , intent(out):: fmax_o(:) ! output grid: %fmax -! -! !CALLED FROM: -! subroutine mksrfdat in module mksrfdatMod -! -! !REVISION HISTORY: -! Revised: Nan Rosenbloom - used mkglacier.F90 as template. -! Original Author: Mariana Vertenstein -! -! -! !LOCAL VARIABLES: -!EOP - type(gridmap_type) :: tgridmap - type(domain_type) :: tdomain ! local domain - real(r8), allocatable :: fmax_i(:) ! input grid: percent fmax - real(r8), allocatable :: frac_dst(:) ! output fractions - real(r8), allocatable :: mask_r8(:) ! float of tdomain%mask - real(r8) :: sum_fldi ! global sum of dummy input fld - real(r8) :: sum_fldo ! global sum of dummy output fld - real(r8) :: gfmax_i ! input grid: global fmax - real(r8) :: garea_i ! input grid: global area - real(r8) :: gfmax_o ! output grid: global fmax - real(r8) :: garea_o ! output grid: global area - integer :: k,n,m,ni,no,ns_i,ns_o ! indices - integer :: ncid,dimid,varid ! input netCDF id's - integer :: ier ! error status - real(r8) :: relerr = 0.00001 ! max error: sum overlap wts ne 1 - character(len=32) :: subname = 'mkfmax' -!----------------------------------------------------------------------- - - write (6,*) 'Attempting to make %fmax .....' - call shr_sys_flush(6) - - ! ----------------------------------------------------------------- - ! Read input file - ! ----------------------------------------------------------------- - - ! Obtain input grid info, read local fields - - call domain_read(tdomain,datfname) - ns_i = tdomain%ns - ns_o = ldomain%ns - allocate(fmax_i(ns_i), stat=ier) - if (ier/=0) call abort() - allocate(frac_dst(ns_o), stat=ier) - if (ier/=0) call abort() - - write (6,*) 'Open soil fmax file: ', trim(datfname) - call check_ret(nf_open(datfname, 0, ncid), subname) - call check_ret(nf_inq_varid (ncid, 'FMAX', varid), subname) - call check_ret(nf_get_var_double (ncid, varid, fmax_i), subname) - call check_ret(nf_close(ncid), subname) - - ! Area-average percent cover on input grid to output grid - ! and correct according to land landmask - ! Note that percent cover is in terms of total grid area. - - call gridmap_mapread(tgridmap, mapfname ) - - ! Error checks for domain and map consistencies - - call domain_checksame( tdomain, ldomain, tgridmap ) - - ! Obtain frac_dst - call gridmap_calc_frac_dst(tgridmap, tdomain%mask, frac_dst) - - ! Determine fmax_o on output grid - - ! In points with no data, use globalAvg - ! (WJS (3-11-13): use real(.365783,r8) rather than .365783_r8 to maintain bfb results - ! with old code) - call gridmap_areaave_srcmask(tgridmap, fmax_i, fmax_o, nodata=real(.365783,r8), mask_src=tdomain%mask, frac_dst=frac_dst) - - ! Check for conservation - - do no = 1, ns_o - if ((fmax_o(no)) > 1.000001_r8) then - write (6,*) 'MKFMAX error: fmax = ',fmax_o(no), & - ' greater than 1.000001 for column, row = ',no - call shr_sys_flush(6) - call abort() - end if - enddo - - ! Global sum of output field -- must multiply by fraction of - ! output grid that is land as determined by input grid - - allocate(mask_r8(ns_i), stat=ier) - if (ier/=0) call abort() - mask_r8 = tdomain%mask - call gridmap_check( tgridmap, mask_r8, frac_dst, subname ) - - ! ----------------------------------------------------------------- - ! Error check2 - ! Compare global areas on input and output grids - ! ----------------------------------------------------------------- - - gfmax_i = 0. - garea_i = 0. - do ni = 1,ns_i - garea_i = garea_i + tgridmap%area_src(ni)*re**2 - gfmax_i = gfmax_i + fmax_i(ni)*(tgridmap%area_src(ni)/100.)* & - tdomain%mask(ni)*re**2 - end do - - gfmax_o = 0. - garea_o = 0. - do no = 1,ns_o - garea_o = garea_o + tgridmap%area_dst(no)*re**2 - gfmax_o = gfmax_o + fmax_o(no)*(tgridmap%area_dst(no)/100.) * & - frac_dst(no)*re**2 - if ((frac_dst(no) < 0.0) .or. (frac_dst(no) > 1.0001)) then - write(6,*) "ERROR:: frac_dst out of range: ", frac_dst(no),no - call abort() - end if - end do - - ! Diagnostic output - - write (ndiag,*) - write (ndiag,'(1x,70a1)') ('=',k=1,70) - write (ndiag,*) 'Maximum Fractional Saturated Area Output' - write (ndiag,'(1x,70a1)') ('=',k=1,70) - - write (ndiag,*) - write (ndiag,'(1x,70a1)') ('.',k=1,70) - write (ndiag,2001) -2001 format (1x,'surface type input grid area output grid area'/ & - 1x,' 10**6 km**2 10**6 km**2 ') - write (ndiag,'(1x,70a1)') ('.',k=1,70) - write (ndiag,*) - write (ndiag,2002) gfmax_i*1.e-06,gfmax_o*1.e-06 - write (ndiag,2004) garea_i*1.e-06,garea_o*1.e-06 -2002 format (1x,'fmax ',f14.3,f17.3) -2004 format (1x,'all surface ',f14.3,f17.3) - - write (6,*) 'Successfully made %fmax' - write (6,*) - call shr_sys_flush(6) - - ! Deallocate dynamic memory - - call domain_clean(tdomain) - call gridmap_clean(tgridmap) - deallocate (fmax_i) - deallocate (frac_dst) - deallocate (mask_r8) - -end subroutine mkfmax - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: mksoilAtt -! -! !INTERFACE: -subroutine mksoilAtt( ncid, dynlanduse, xtype ) -! -! !DESCRIPTION: -! add atttributes to output file regarding the soil module -! -! !USES: - use fileutils , only : get_filename - use mkncdio , only : check_ret, ncd_defvar, ncd_def_spatial_var - use mkvarpar - use mkvarctl - -! !ARGUMENTS: - implicit none - include 'netcdf.inc' - integer, intent(in) :: ncid ! NetCDF file ID to write out to - logical, intent(in) :: dynlanduse ! if dynamic land-use file - integer, intent(in) :: xtype ! external type to output real data as -! -! !CALLED FROM: -! subroutine mkfile in module mkfileMod -! -! !REVISION HISTORY: -! Original Author: Erik Kluzek -! -! -! !LOCAL VARIABLES: -!EOP - integer :: dimid ! temporary - character(len=256) :: str ! global attribute string - character(len=32) :: subname = 'mksoilAtt' -!----------------------------------------------------------------------- - - if (.not. dynlanduse) then - - ! Define dimensions unique to soil - - call check_ret(nf_def_dim (ncid, 'nlevsoi', & - nlevsoi , dimid), subname) - - ! Add global attributes to file - - if ( soil_clay /= unset .and. soil_sand /= unset )then - str = 'TRUE' - call check_ret(nf_put_att_text (ncid, NF_GLOBAL, & - 'soil_clay_override', len_trim(str), trim(str)), subname) - str = 'TRUE' - call check_ret(nf_put_att_text (ncid, NF_GLOBAL, & - 'soil_sand_override', len_trim(str), trim(str)), subname) - else - str = get_filename(mksrf_fsoitex) - call check_ret(nf_put_att_text(ncid, NF_GLOBAL, & - 'Soil_texture_raw_data_file_name', len_trim(str), trim(str)), subname) - end if - if ( soil_color /= unsetcol )then - str = 'TRUE' - call check_ret(nf_put_att_text (ncid, NF_GLOBAL, & - 'soil_color_override', len_trim(str), trim(str)), subname) - else - str = get_filename(mksrf_fsoicol) - call check_ret(nf_put_att_text(ncid, NF_GLOBAL, & - 'Soil_color_raw_data_file_name', len_trim(str), trim(str)), subname) - end if - if ( soil_fmax /= unset )then - str = 'TRUE' - call check_ret(nf_put_att_text (ncid, NF_GLOBAL, & - 'soil_fmax_override', len_trim(str), trim(str)), subname) - else - str = get_filename(mksrf_fmax) - call check_ret(nf_put_att_text(ncid, NF_GLOBAL, & - 'Fmax_raw_data_file_name', len_trim(str), trim(str)), subname) - end if - str = get_filename(mksrf_forganic) - call check_ret(nf_put_att_text(ncid, NF_GLOBAL, & - 'Organic_matter_raw_data_file_name', len_trim(str), trim(str)), subname) - - ! Define variables - - call ncd_defvar(ncid=ncid, varname='mxsoil_color', xtype=nf_int, & - long_name='maximum numbers of soil colors', units='unitless') - - call ncd_def_spatial_var(ncid=ncid, varname='SOIL_COLOR', xtype=nf_int, & - long_name='soil color', units='unitless') - - call ncd_def_spatial_var(ncid=ncid, varname='PCT_SAND', xtype=xtype, & - lev1name='nlevsoi', & - long_name='percent sand', units='unitless') - - call ncd_def_spatial_var(ncid=ncid, varname='PCT_CLAY', xtype=xtype, & - lev1name='nlevsoi', & - long_name='percent clay', units='unitless') - - call ncd_def_spatial_var(ncid=ncid, varname='ORGANIC', xtype=xtype, & - lev1name='nlevsoi', & - long_name='organic matter density at soil levels', & - units='kg/m3 (assumed carbon content 0.58 gC per gOM)') - - call ncd_def_spatial_var(ncid=ncid, varname='FMAX', xtype=xtype, & - long_name='maximum fractional saturated area', units='unitless') - - end if - -end subroutine mksoilAtt - -!----------------------------------------------------------------------- - -end module mksoilMod diff --git a/tools/mksurfdata_map/src/mksoilUtilsMod.F90 b/tools/mksurfdata_map/src/mksoilUtilsMod.F90 deleted file mode 100644 index 122cfd45d5..0000000000 --- a/tools/mksurfdata_map/src/mksoilUtilsMod.F90 +++ /dev/null @@ -1,224 +0,0 @@ -module mksoilUtilsMod - - !----------------------------------------------------------------------- - !BOP - ! - ! !MODULE: mksoilUtils - ! - ! !DESCRIPTION: - ! Lower-level utilities used in making soil data. - ! - ! These are separated out from mksoilMod mainly as an aid to testing. - ! - ! !REVISION HISTORY: - ! Author: Bill Sacks - ! - !----------------------------------------------------------------------- - !!USES: - use shr_kind_mod, only : r8 => shr_kind_r8 - use mkgridmapMod, only : gridmap_type - - implicit none - private - - ! - ! !PUBLIC MEMBER FUNCTIONS: - ! - public :: dominant_soil_color - public :: mkrank - - ! - ! !PRIVATE MEMBER FUNCTIONS: - ! - - !EOP - !=============================================================== -contains - !=============================================================== - - !----------------------------------------------------------------------- - subroutine dominant_soil_color(tgridmap, mask_i, soil_color_i, nsoicol, soil_color_o) - ! - ! !DESCRIPTION: - ! Determine the dominant soil color in each output cell - ! - ! !ARGUMENTS: - type(gridmap_type) , intent(in) :: tgridmap - integer , intent(in) :: mask_i(:) ! input grid: land mask (1 = land, 0 = ocean) - integer , intent(in) :: soil_color_i(:) ! input grid: BATS soil color - integer , intent(in) :: nsoicol ! number of soil colors - integer , intent(out) :: soil_color_o(:) ! output grid: soil color classes - ! - ! !LOCAL VARIABLES: - integer, parameter :: num = 2 ! set soil mapunit number - integer :: wsti(num) ! index to 1st and 2nd largest wst - integer :: k, n, ni, no, ns_i, ns_o - real(r8) :: wt ! map overlap weight - real(r8), allocatable :: wst(:,:) ! overlap weights, by surface type - logical :: has_color ! whether this grid cell has non-zero color - integer, parameter :: miss = 99999 ! missing data indicator - - character(len=*), parameter :: subname = 'dominant_soil_color' - !----------------------------------------------------------------------- - - ns_i = size(mask_i) - if (size(soil_color_i) /= ns_i) then - write(6,*) subname, ' ERROR: size of soil_color_i should match size of mask_i' - write(6,*) 'size(mask_i), size(soil_color_i) = ', & - size(mask_i), size(soil_color_i) - call abort() - end if - - ! find area of overlap for each soil color for each no - - ns_o = size(soil_color_o) - allocate(wst(0:nsoicol,ns_o)) - wst(0:nsoicol,:) = 0 - - ! TODO: need to do a loop to determine - ! the maximum number of over lap cells throughout the grid - ! first get an array that is novr(ns_o) and fill this in - then set - ! maxovr - to max(novr) - then allocate the array wst to be size of - ! maxovr,ns_o or 0:nsoilcol,ns_o - - do n = 1,tgridmap%ns - ni = tgridmap%src_indx(n) - no = tgridmap%dst_indx(n) - wt = tgridmap%wovr(n) * mask_i(ni) - k = soil_color_i(ni) * mask_i(ni) - wst(k,no) = wst(k,no) + wt - enddo - - soil_color_o(:) = 0 - do no = 1,ns_o - - ! If the output cell has any non-zero-colored inputs, then set the weight of - ! zero-colored inputs to 0, to ensure that the zero-color is NOT dominant. - if (any(wst(1:nsoicol,no) > 0.)) then - has_color = .true. - wst(0,no) = 0.0 - else - has_color = .false. - end if - - ! Rank non-zero weights by color type. wsti(1) is the most extensive - ! color type. - - if (has_color) then - call mkrank (nsoicol, wst(0:nsoicol,no), miss, wsti, num) - soil_color_o(no) = wsti(1) - end if - - ! If land but no color, set color to 15 (in older dataset generic - ! soil color 4) - - if (nsoicol == 8) then - if (soil_color_o(no)==0) then - soil_color_o(no) = 4 - end if - else if (nsoicol == 20) then - if (soil_color_o(no)==0) then - soil_color_o(no) = 15 - end if - else - write(6,*) 'MKSOILCOL error: unhandled nsoicol: ', nsoicol - call abort() - end if - - ! Error checks - - if (soil_color_o(no) < 0 .or. soil_color_o(no) > nsoicol) then - write (6,*) 'MKSOILCOL error: land model soil color = ', & - soil_color_o(no),' is not valid for lon,lat = ',no - call abort() - end if - - end do - - deallocate (wst) - - end subroutine dominant_soil_color - - - !----------------------------------------------------------------------- - !BOP - ! - ! !ROUTINE: mkrank - ! - ! !INTERFACE: - subroutine mkrank (n, a, miss, iv, num) - ! - ! !DESCRIPTION: - ! Return indices of largest [num] values in array [a]. - ! - ! !ARGUMENTS: - integer , intent(in) :: n !array length - real(r8), intent(in) :: a(0:n) !array to be ranked - integer , intent(in) :: miss !missing data value - integer , intent(in) :: num !number of largest values requested - integer , intent(out):: iv(num) !index to [num] largest values in array [a] - ! - ! !REVISION HISTORY: - ! Author: Gordon Bonan - ! - ! !LOCAL VARIABLES: - !EOP - real(r8) a_max !maximum value in array - integer i !array index - real(r8) delmax !tolerance for finding if larger value - integer m !do loop index - integer k !do loop index - logical exclude !true if data value has already been chosen - !----------------------------------------------------------------------- - - delmax = 1.e-06 - - ! Find index of largest non-zero number - - iv(1) = miss - a_max = -9999. - - do i = 0, n - if (a(i)>0. .and. (a(i)-a_max)>delmax) then - a_max = a(i) - iv(1) = i - end if - end do - - ! iv(1) = miss indicates no values > 0. this is an error - - if (iv(1) == miss) then - write (6,*) 'MKRANK error: iv(1) = missing' - call abort() - end if - - ! Find indices of the next [num]-1 largest non-zero number. - ! iv(m) = miss if there are no more values > 0 - - do m = 2, num - iv(m) = miss - a_max = -9999. - do i = 0, n - - ! exclude if data value has already been chosen - - exclude = .false. - do k = 1, m-1 - if (i == iv(k)) exclude = .true. - end do - - ! if not already chosen, see if it is the largest of - ! the remaining values - - if (.not. exclude) then - if (a(i)>0. .and. (a(i)-a_max)>delmax) then - a_max = a(i) - iv(m) = i - end if - end if - end do - end do - - end subroutine mkrank - -end module mksoilUtilsMod diff --git a/tools/mksurfdata_map/src/mksoildepthMod.F90 b/tools/mksurfdata_map/src/mksoildepthMod.F90 deleted file mode 100644 index c69cf375a4..0000000000 --- a/tools/mksurfdata_map/src/mksoildepthMod.F90 +++ /dev/null @@ -1,172 +0,0 @@ -module mksoildepthMod - -!----------------------------------------------------------------------- -!BOP -! -! !MODULE: mksoildepthMod -! -! !DESCRIPTION: -! make fraction soildepth from input soildepth data -! -! !REVISION HISTORY: -! Author: Sam Levis and Bill Sacks -! -!----------------------------------------------------------------------- -! -! !USES: - use shr_kind_mod, only : r8 => shr_kind_r8 - use shr_sys_mod , only : shr_sys_flush - use mkdomainMod , only : domain_checksame - - implicit none - - private - -! !PUBLIC MEMBER FUNCTIONS: - public mksoildepth ! regrid soildepth data -! -!EOP -!=============================================================== -contains -!=============================================================== - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: mksoildepth -! -! !INTERFACE: -subroutine mksoildepth(ldomain, mapfname, datfname, ndiag, soildepth_o) -! -! !DESCRIPTION: -! make soildepth -! -! !USES: - use mkdomainMod, only : domain_type, domain_clean, domain_read - use mkgridmapMod - use mkncdio - use mkdiagnosticsMod, only : output_diagnostics_area - use mkchecksMod, only : min_bad, max_bad -! -! !ARGUMENTS: - - implicit none - type(domain_type) , intent(in) :: ldomain - character(len=*) , intent(in) :: mapfname ! input mapping file name - character(len=*) , intent(in) :: datfname ! input data file name - integer , intent(in) :: ndiag ! unit number for diag out - real(r8) , intent(out):: soildepth_o(:) ! output grid: fraction soildepth -! -! !CALLED FROM: -! subroutine mksrfdat in module mksrfdatMod -! -! !REVISION HISTORY: -! Author: Sam Levis and Bill Sacks -! -! -! !LOCAL VARIABLES: -!EOP - type(gridmap_type) :: tgridmap - type(domain_type) :: tdomain ! local domain - real(r8), allocatable :: data_i(:) ! data on input grid - real(r8), allocatable :: frac_dst(:) ! output fractions - real(r8), allocatable :: mask_r8(:) ! float of tdomain%mask - integer :: ncid,varid ! input netCDF id's - integer :: ier ! error status - - real(r8), parameter :: min_valid = 0._r8 ! minimum valid value - real(r8), parameter :: max_valid = 100.000001_r8 ! maximum valid value - character(len=32) :: subname = 'mksoildepth' - character(len=32) :: varname - integer :: varnum -!----------------------------------------------------------------------- - - write (6,*) 'Attempting to make soildepth .....' - call shr_sys_flush(6) - - ! ----------------------------------------------------------------- - ! Read domain and mapping information, check for consistency - ! ----------------------------------------------------------------- - - call domain_read( tdomain, datfname ) - - call gridmap_mapread( tgridmap, mapfname ) - - ! Obtain frac_dst - allocate(frac_dst(ldomain%ns), stat=ier) - if (ier/=0) call abort() - call gridmap_calc_frac_dst(tgridmap, tdomain%mask, frac_dst) - - allocate(mask_r8(tdomain%ns), stat=ier) - if (ier/=0) call abort() - mask_r8 = tdomain%mask - call gridmap_check( tgridmap, mask_r8, frac_dst, subname ) - - call domain_checksame( tdomain, ldomain, tgridmap ) - - ! ----------------------------------------------------------------- - ! Open input file, allocate memory for input data - ! ----------------------------------------------------------------- - - write(6,*)'Open soildepth file: ', trim(datfname) - call check_ret(nf_open(datfname, 0, ncid), subname) - - allocate(data_i(tdomain%ns), stat=ier) - if (ier/=0) call abort() - - ! ----------------------------------------------------------------- - ! Regrid soildepth - ! ----------------------------------------------------------------- - - varnum = 1 - select case (varnum) - case(1) - varname = 'Avg_Depth_Median' - case(2) - varname = 'Avg_Depth_Mean' - case(3) - varname = 'Upland_Valley_Depth_Median' - case(4) - varname = 'Upland_Valley_Depth_Mean' - case(5) - varname = 'Upland_Hillslope_Depth_Median' - case(6) - varname = 'Upland_Hillslope_Depth_Mean' - case(7) - varname = 'Lowland_Depth_Mean' - case(8) - varname = 'Lowland_Depth_Mean' - end select - -! call check_ret(nf_inq_varid (ncid, 'Avg_Depth_Median', varid), subname) - call check_ret(nf_inq_varid (ncid, varname, varid), subname) - call check_ret(nf_get_var_double (ncid, varid, data_i), subname) - call gridmap_areaave_srcmask(tgridmap, data_i, soildepth_o, nodata=0._r8, mask_src=tdomain%mask, frac_dst=frac_dst) - - ! Check validity of output data - if (min_bad(soildepth_o, min_valid, 'soildepth') .or. & - max_bad(soildepth_o, max_valid, 'soildepth')) then - call abort() - end if - - call output_diagnostics_area(data_i, soildepth_o, tgridmap, "Soildepth", percent=.false., ndiag=ndiag, mask_src=tdomain%mask, frac_dst=frac_dst) - - ! ----------------------------------------------------------------- - ! Close files and deallocate dynamic memory - ! ----------------------------------------------------------------- - - call check_ret(nf_close(ncid), subname) - call domain_clean(tdomain) - call gridmap_clean(tgridmap) - deallocate (data_i) - deallocate (frac_dst) - deallocate (mask_r8) - - write (6,*) 'Successfully made soildepth' - write (6,*) - call shr_sys_flush(6) - -end subroutine mksoildepth - - -end module mksoildepthMod diff --git a/tools/mksurfdata_map/src/mksurfdat.F90 b/tools/mksurfdata_map/src/mksurfdat.F90 deleted file mode 100644 index aa965f097d..0000000000 --- a/tools/mksurfdata_map/src/mksurfdat.F90 +++ /dev/null @@ -1,1630 +0,0 @@ -program mksurfdat - -!----------------------------------------------------------------------- -!BOP -! -! !PROGRAM: mksurfdat -! -! !DESCRIPTION: -! Creates land model surface dataset from original "raw" data files. -! Surface dataset contains model grid, pfts, inland water, glacier, -! soil texture, soil color, LAI and SAI, urban fraction, and urban -! parameters. -! -! !USES: - use shr_kind_mod , only : r8 => shr_kind_r8, r4 => shr_kind_r4 - use fileutils , only : opnfil, getavu - use mklaiMod , only : mklai - use mkpctPftTypeMod , only : pct_pft_type, get_pct_p2l_array, get_pct_l2g_array, update_max_array - use mkpftConstantsMod , only : natpft_lb, natpft_ub, cft_lb, cft_ub, num_cft - use mkpftMod , only : pft_idx, pft_frc, mkpft, mkpftInit, mkpft_parse_oride - use mksoilMod , only : soil_sand, soil_clay, mksoiltex, mksoilInit, & - soil_color, mksoilcol, mkorganic, & - soil_fmax, mkfmax - use mkvocefMod , only : mkvocef - use mklanwatMod , only : mklakwat, mkwetlnd, mklakparams - use mkglacierregionMod , only : mkglacierregion - use mkglcmecMod , only : nglcec, mkglcmec, mkglcmecInit, mkglacier - use mkharvestMod , only : mkharvest, mkharvest_init, mkharvest_fieldname - use mkharvestMod , only : mkharvest_numtypes, mkharvest_parse_oride - use mkharvestMod , only : harvestDataType - use mkurbanparCommonMod, only : mkelev - use mkurbanparMod , only : mkurbanInit, mkurban, mkurbanpar, numurbl - use mkutilsMod , only : normalize_classes_by_gcell - use mkfileMod , only : mkfile - use mkvarpar , only : nlevsoi, elev_thresh, numstdpft - use mkvarctl - use nanMod , only : nan, bigint - use mkncdio , only : check_ret, ncd_put_time_slice - use mkdomainMod , only : domain_type, domain_read_map, domain_read - use mkdomainMod , only : domain_write, is_domain_0to360_longs - use mkgdpMod , only : mkgdp - use mkpeatMod , only : mkpeat - use mksoildepthMod , only : mksoildepth - use mkagfirepkmonthMod , only : mkagfirepkmon - use mktopostatsMod , only : mktopostats - use mkVICparamsMod , only : mkVICparams -! -! !ARGUMENTS: - implicit none - - include 'netcdf.inc' -! -! !REVISION HISTORY: -! Authors: Gordon Bonan, Sam Levis and Mariana Vertenstein -! Revised: Nan Rosenbloom to add fmax processing. -! 3/18/08: David Lawrence added organic matter processing -! 1/22/09: Keith Oleson added urban parameter processing -! 2/11/13: Sam Levis added abm, peat, and gdp processing for new fire model -! -! -! !LOCAL VARIABLES: -!EOP - integer :: nsoicol ! number of model color classes - integer :: k,m,n ! indices - integer :: ni,nj,ns_o ! indices - integer :: ier ! error status - integer :: ndiag,nfdyn ! unit numbers - integer :: ncid ! netCDF id - integer :: omode ! netCDF output mode - integer :: varid ! netCDF variable id - integer :: ret ! netCDF return status - integer :: ntim ! time sample for dynamic land use - integer :: year ! year for dynamic land use - integer :: year2 ! year for dynamic land use for harvest file - logical :: all_veg ! if gridcell will be 100% vegetated land-cover - real(r8) :: suma ! sum for error check - character(len=256) :: fgrddat ! grid data file - character(len=256) :: fsurdat ! output surface data file name (if blank, do not output a surface dataset) - character(len=256) :: fsurlog ! output surface log file name - character(len=256) :: fdyndat ! dynamic landuse data file name - character(len=256) :: fname ! generic filename - character(len=256) :: fhrvname ! generic harvest filename - character(len=256) :: string ! string read in - integer :: t1 ! timer - real(r8),parameter :: p5 = 0.5_r8 ! constant - real(r8),parameter :: p25 = 0.25_r8 ! constant - - real(r8), allocatable :: landfrac_pft(:) ! PFT data: % land per gridcell - real(r8), allocatable :: pctlnd_pft(:) ! PFT data: % of gridcell for PFTs - real(r8), allocatable :: pctlnd_pft_dyn(:) ! PFT data: % of gridcell for dyn landuse PFTs - integer , allocatable :: pftdata_mask(:) ! mask indicating real or fake land type - type(pct_pft_type), allocatable :: pctnatpft(:) ! % of grid cell that is nat veg, and breakdown into PFTs - type(pct_pft_type), allocatable :: pctnatpft_max(:) ! % of grid cell maximum PFTs of the time series - type(pct_pft_type), allocatable :: pctcft(:) ! % of grid cell that is crop, and breakdown into CFTs - type(pct_pft_type), allocatable :: pctcft_max(:) ! % of grid cell maximum CFTs of the time series - real(r8) :: harvest_initval ! initial value for harvest variables - real(r8), pointer :: harvest1D(:) ! harvest 1D data: normalized harvesting - real(r8), pointer :: harvest2D(:,:) ! harvest 1D data: normalized harvesting - real(r8), allocatable :: pctgla(:) ! percent of grid cell that is glacier - real(r8), allocatable :: pctglc_gic(:) ! percent of grid cell that is gic (% of glc landunit) - real(r8), allocatable :: pctglc_icesheet(:) ! percent of grid cell that is ice sheet (% of glc landunit) - real(r8), allocatable :: pctglcmec(:,:) ! glacier_mec pct coverage in each class (% of landunit) - real(r8), allocatable :: topoglcmec(:,:) ! glacier_mec sfc elevation in each gridcell and class - real(r8), allocatable :: pctglcmec_gic(:,:) ! GIC pct coverage in each class (% of landunit) - real(r8), allocatable :: pctglcmec_icesheet(:,:) ! icesheet pct coverage in each class (% of landunit) - real(r8), allocatable :: elevclass(:) ! glacier_mec elevation classes - integer, allocatable :: glacier_region(:) ! glacier region ID - real(r8), allocatable :: pctlak(:) ! percent of grid cell that is lake - real(r8), allocatable :: pctwet(:) ! percent of grid cell that is wetland - real(r8), allocatable :: pcturb(:) ! percent of grid cell that is urbanized (total across all urban classes) - real(r8), allocatable :: urbn_classes(:,:) ! percent cover of each urban class, as % of total urban area - real(r8), allocatable :: urbn_classes_g(:,:)! percent cover of each urban class, as % of grid cell - real(r8), allocatable :: elev(:) ! glc elevation (m) - real(r8), allocatable :: fmax(:) ! fractional saturated area - integer , allocatable :: soicol(:) ! soil color - real(r8), allocatable :: pctsand(:,:) ! soil texture: percent sand - real(r8), allocatable :: pctclay(:,:) ! soil texture: percent clay - real(r8), allocatable :: ef1_btr(:) ! Isoprene emission factor for broadleaf - real(r8), allocatable :: ef1_fet(:) ! Isoprene emission factor for fine/everg - real(r8), allocatable :: ef1_fdt(:) ! Isoprene emission factor for fine/dec - real(r8), allocatable :: ef1_shr(:) ! Isoprene emission factor for shrubs - real(r8), allocatable :: ef1_grs(:) ! Isoprene emission factor for grasses - real(r8), allocatable :: ef1_crp(:) ! Isoprene emission factor for crops - real(r8), allocatable :: organic(:,:) ! organic matter density (kg/m3) - real(r8), allocatable :: gdp(:) ! GDP (x1000 1995 US$/capita) - real(r8), allocatable :: fpeat(:) ! peatland fraction of gridcell - real(r8), allocatable :: soildepth(:) ! soil depth (m) - integer , allocatable :: agfirepkmon(:) ! agricultural fire peak month - integer , allocatable :: urban_region(:) ! urban region ID - real(r8), allocatable :: topo_stddev(:) ! standard deviation of elevation (m) - real(r8), allocatable :: slope(:) ! topographic slope (degrees) - real(r8), allocatable :: vic_binfl(:) ! VIC b parameter (unitless) - real(r8), allocatable :: vic_ws(:) ! VIC Ws parameter (unitless) - real(r8), allocatable :: vic_dsmax(:) ! VIC Dsmax parameter (mm/day) - real(r8), allocatable :: vic_ds(:) ! VIC Ds parameter (unitless) - real(r8), allocatable :: lakedepth(:) ! lake depth (m) - - real(r8) :: std_elev = -999.99_r8 ! Standard deviation of elevation (m) to use for entire grid - - integer, allocatable :: harvind1D(:) ! Indices of 1D harvest fields - integer, allocatable :: harvind2D(:) ! Indices of 2D harvest fields - - ! NOTE(bja, 2015-01) added to work around a ?bug? causing 1x1_urbanc_alpha to abort. See - !/glade/p/cesm/cseg/inputdata/lnd/clm2/surfdata_map/README_c141219 - logical :: urban_skip_abort_on_invalid_data_check - - type(domain_type) :: ldomain - - character(len=32) :: subname = 'mksrfdat' ! program name - type(harvestDataType) :: harvdata - - namelist /clmexp/ & - mksrf_fgrid, & - mksrf_gridtype, & - mksrf_fvegtyp, & - mksrf_fhrvtyp, & - mksrf_fsoitex, & - mksrf_forganic, & - mksrf_fsoicol, & - mksrf_fvocef, & - mksrf_flakwat, & - mksrf_fwetlnd, & - mksrf_fglacier, & - mksrf_fglacierregion, & - mksrf_furbtopo, & - mksrf_fmax, & - mksrf_furban, & - mksrf_flai, & - mksrf_fdynuse, & - mksrf_fgdp, & - mksrf_fpeat, & - mksrf_fsoildepth, & - mksrf_fabm, & - mksrf_ftopostats, & - mksrf_fvic, & - nglcec, & - numpft, & - soil_color, & - soil_sand, & - soil_fmax, & - soil_clay, & - pft_idx, & - all_veg, & - pft_frc, & - all_urban, & - no_inlandwet, & - map_fpft, & - map_flakwat, & - map_fwetlnd, & - map_fglacier, & - map_fglacierregion, & - map_fsoitex, & - map_fsoicol, & - map_furban, & - map_furbtopo, & - map_fmax, & - map_forganic, & - map_fvocef, & - map_flai, & - map_fharvest, & - map_fgdp, & - map_fpeat, & - map_fsoildepth, & - map_fabm, & - map_ftopostats, & - map_fvic, & - gitdescribe, & - outnc_large_files, & - outnc_double, & - outnc_dims, & - outnc_vic, & - outnc_3dglc, & - fsurdat, & - fdyndat, & - fsurlog, & - std_elev, & - urban_skip_abort_on_invalid_data_check - -!----------------------------------------------------------------------- - - ! ====================================================================== - ! Read input namelist - ! ====================================== - ! Must specify settings for the output grid: - ! ====================================== - ! mksrf_fgrid -- Grid dataset - ! ====================================== - ! Must specify settings for input high resolution datafiles - ! ====================================== - ! mksrf_fglacier - Glacier dataset - ! mksrf_fglacierregion - Glacier region ID dataset - ! mksrf_flai ----- Leaf Area Index dataset - ! mksrf_flakwat -- Lake water dataset - ! mksrf_fwetlnd -- Wetland water dataset - ! mksrf_forganic - Organic soil carbon dataset - ! mksrf_fmax ----- Max fractional saturated area dataset - ! mksrf_fsoicol -- Soil color dataset - ! mksrf_fsoitex -- Soil texture dataset - ! mksrf_furbtopo-- Topography dataset (for limiting urban areas) - ! mksrf_furban --- Urban dataset - ! mksrf_fvegtyp -- PFT vegetation type dataset - ! mksrf_fhrvtyp -- harvest type dataset - ! mksrf_fvocef -- Volatile Organic Compund Emission Factor dataset - ! mksrf_fgdp ----- GDP dataset - ! mksrf_fpeat ---- Peatland dataset - ! mksrf_fsoildepth Soil depth dataset - ! mksrf_fabm ----- Agricultural fire peak month dataset - ! mksrf_ftopostats Topography statistics dataset - ! mksrf_fvic ----- VIC parameters dataset - ! ====================================== - ! Must specify mapping file for the different datafiles above - ! ====================================== - ! map_fpft -------- Mapping for mksrf_fvegtyp - ! map_flakwat ----- Mapping for mksrf_flakwat - ! map_fwetlnd ----- Mapping for mksrf_fwetlnd - ! map_fglacier ---- Mapping for mksrf_fglacier - ! map_fglacierregion - Mapping for mksrf_fglacierregion - ! map_fsoitex ----- Mapping for mksrf_fsoitex - ! map_fsoicol ----- Mapping for mksrf_fsoicol - ! map_furban ------ Mapping for mksrf_furban - ! map_furbtopo ---- Mapping for mksrf_furbtopo - ! map_fmax -------- Mapping for mksrf_fmax - ! map_forganic ---- Mapping for mksrf_forganic - ! map_fvocef ------ Mapping for mksrf_fvocef - ! map_flai -------- Mapping for mksrf_flai - ! map_fharvest ---- Mapping for mksrf_flai harvesting - ! map_fgdp -------- Mapping for mksrf_fgdp - ! map_fpeat ------- Mapping for mksrf_fpeat - ! map_fsoildepth -- Mapping for mksrf_fsoildepth - ! map_fabm -------- Mapping for mksrf_fabm - ! map_ftopostats -- Mapping for mksrf_ftopostats - ! map_fvic -------- Mapping for mksrf_fvic - ! ====================================== - ! Optionally specify setting for: - ! ====================================== - ! mksrf_fdynuse ----- ASCII text file that lists each year of pft files to use - ! mksrf_gridtype ---- Type of grid (default is 'global') - ! outnc_double ------ If output should be in double precision - ! outnc_large_files - If output should be in NetCDF large file format - ! outnc_vic --------- Output fields needed for VIC - ! outnc_3dglc ------- Output 3D glacier fields (normally only needed for comparasion) - ! nglcec ------------ If you want to change the number of Glacier elevation classes - ! gitdescribe ------- Description of this version from git - ! ====================================== - ! Optional settings to change values for entire area - ! ====================================== - ! all_urban --------- If entire area is urban - ! all_veg ----------- If entire area is to be vegetated (pft_idx and pft_frc then required) - ! no_inlandwet ------ If wetland should be set to 0% over land - ! soil_color -------- If you want to change the soil_color to this value everywhere - ! soil_clay --------- If you want to change the soil_clay % to this value everywhere - ! soil_fmax --------- If you want to change the soil_fmax to this value everywhere - ! soil_sand --------- If you want to change the soil_sand % to this value everywhere - ! pft_idx ----------- If you want to change to 100% veg covered with given PFT indices - ! pft_frc ----------- Fractions that correspond to the pft_idx above - ! ================== - ! numpft (if different than default of 16) - ! ====================================== - ! Optional settings to work around urban bug? - ! ====================================== - ! urban_skip_abort_on_invalid_data_check - ! ====================================================================== - - write(6,*) 'Attempting to initialize control settings .....' - - mksrf_gridtype = 'global' - outnc_large_files = .false. - outnc_double = .true. - outnc_vic = .false. - outnc_3dglc = .false. - all_urban = .false. - all_veg = .false. - no_inlandwet = .true. - - ! default value for bug work around - urban_skip_abort_on_invalid_data_check = .false. - - read(5, clmexp, iostat=ier) - if (ier /= 0) then - write(6,*)'error: namelist input resulted in error code ',ier - call abort() - endif - - write (6,*) 'Attempting to create surface boundary data .....' - write (6,'(72a1)') ("-",n=1,60) - - ! ---------------------------------------------------------------------- - ! Error check namelist input - ! ---------------------------------------------------------------------- - - if (urban_skip_abort_on_invalid_data_check) then - write(6, *) "WARNING: aborting on invalid data check in urban has been disabled!" - write(6, *) "WARNING: urban data may be invalid!" - end if - - if (mksrf_fgrid /= ' ')then - fgrddat = mksrf_fgrid - write(6,*)'mksrf_fgrid = ',mksrf_fgrid - else - write (6,*)'must specify mksrf_fgrid' - call abort() - endif - - if (trim(mksrf_gridtype) == 'global' .or. & - trim(mksrf_gridtype) == 'regional') then - write(6,*)'mksrf_gridtype = ',trim(mksrf_gridtype) - else - write(6,*)'mksrf_gridtype = ',trim(mksrf_gridtype) - write (6,*)'illegal mksrf_gridtype, must be global or regional ' - call abort() - endif - if ( outnc_large_files )then - write(6,*)'Output file in NetCDF 64-bit large_files format' - end if - if ( outnc_double )then - write(6,*)'Output ALL data in file as 64-bit' - end if - if ( outnc_vic )then - write(6,*)'Output VIC fields' - end if - if ( outnc_3dglc )then - write(6,*)'Output optional 3D glacier fields (mostly used for verification of the glacier model)' - end if - if ( outnc_3dglc )then - write(6,*)'Output optional 3D glacier fields (mostly used for verification of the glacier model)' - end if - if ( all_urban )then - write(6,*) 'Output ALL data in file as 100% urban' - end if - if ( no_inlandwet )then - write(6,*) 'Set wetland to 0% over land' - end if - if (nglcec <= 0) then - write(6,*) 'nglcec must be at least 1' - call abort() - end if - - ! - ! Call module initialization routines - ! - call mksoilInit( ) - call mkpftInit( zero_out_l=all_urban, all_veg_l=all_veg ) - allocate ( elevclass(nglcec+1) ) - call mkglcmecInit (elevclass) - call mkurbanInit (mksrf_furban) - - if ( all_veg )then - write(6,*) 'Output ALL data in file as 100% vegetated' - end if - - ! ---------------------------------------------------------------------- - ! Determine land model grid, fractional land and land mask - ! ---------------------------------------------------------------------- - - write(6,*)'calling domain_read' - if ( .not. domain_read_map(ldomain, fgrddat) )then - call domain_read(ldomain, fgrddat) - end if - write(6,*)'finished domain_read' - - ! Invalidate mask and frac for ldomain - - !ldomain%mask = bigint - !ldomain%frac = nan - - ! Determine if will have 1d output - - if (ldomain%ni /= -9999 .and. ldomain%nj /= -9999) then - write(6,*)'fsurdat is 2d lat/lon grid' - write(6,*)'nlon= ',ldomain%ni,' nlat= ',ldomain%nj - if (outnc_dims == 1) then - write(6,*)' writing output file in 1d gridcell format' - end if - else - write(6,*)'fsurdat is 1d gridcell grid' - outnc_dims = 1 - end if - - outnc_1d = .false. - if ((ldomain%ni == -9999 .and. ldomain%nj == -9999) .or. outnc_dims==1) then - outnc_1d = .true. - write(6,*)'output file will be 1d' - end if - - ! Make sure ldomain is on a 0 to 360 grid as that's a requirement for CESM - if ( .not. is_domain_0to360_longs( ldomain ) )then - write(6,*)' Output domain must be on a 0 to 360 longitude grid rather than a -180 to 180 grid as it is required for CESM' - call abort() - end if - ! ---------------------------------------------------------------------- - ! Allocate and initialize dynamic memory - ! ---------------------------------------------------------------------- - - ns_o = ldomain%ns - allocate ( landfrac_pft(ns_o) , & - pctlnd_pft(ns_o) , & - pftdata_mask(ns_o) , & - pctnatpft(ns_o) , & - pctnatpft_max(ns_o) , & - pctcft(ns_o) , & - pctcft_max(ns_o) , & - pctgla(ns_o) , & - pctlak(ns_o) , & - pctwet(ns_o) , & - pcturb(ns_o) , & - urban_region(ns_o) , & - urbn_classes(ns_o,numurbl) , & - urbn_classes_g(ns_o,numurbl) , & - pctsand(ns_o,nlevsoi) , & - pctclay(ns_o,nlevsoi) , & - soicol(ns_o) , & - gdp(ns_o) , & - fpeat(ns_o) , & - soildepth(ns_o) , & - agfirepkmon(ns_o) , & - topo_stddev(ns_o) , & - slope(ns_o) , & - vic_binfl(ns_o) , & - vic_ws(ns_o) , & - vic_dsmax(ns_o) , & - vic_ds(ns_o) , & - lakedepth(ns_o) , & - glacier_region(ns_o) ) - landfrac_pft(:) = spval - pctlnd_pft(:) = spval - pftdata_mask(:) = -999 - pctgla(:) = spval - pctlak(:) = spval - pctwet(:) = spval - pcturb(:) = spval - urban_region(:) = -999 - urbn_classes(:,:) = spval - urbn_classes_g(:,:) = spval - pctsand(:,:) = spval - pctclay(:,:) = spval - soicol(:) = -999 - gdp(:) = spval - fpeat(:) = spval - soildepth(:) = spval - agfirepkmon(:) = -999 - topo_stddev(:) = spval - slope(:) = spval - vic_binfl(:) = spval - vic_ws(:) = spval - vic_dsmax(:) = spval - vic_ds(:) = spval - lakedepth(:) = spval - glacier_region(:) = -999 - - ! ---------------------------------------------------------------------- - ! Open diagnostic output log file - ! ---------------------------------------------------------------------- - - if (fsurlog == ' ') then - write(6,*)' must specify fsurlog in namelist' - call abort() - else - ndiag = getavu(); call opnfil (fsurlog, ndiag, 'f') - end if - - if (urban_skip_abort_on_invalid_data_check) then - write(ndiag, *) "WARNING: aborting on invalid data check in urban has been disabled!" - write(ndiag, *) "WARNING: urban data may be invalid!" - end if - - if (mksrf_fgrid /= ' ')then - write (ndiag,*)'using fractional land data from file= ', & - trim(mksrf_fgrid),' to create the surface dataset' - endif - - if (trim(mksrf_gridtype) == 'global' .or. & - trim(mksrf_gridtype) == 'regional') then - write(6,*)'mksrf_gridtype = ',trim(mksrf_gridtype) - endif - - write(ndiag,*) 'PFTs from: ',trim(mksrf_fvegtyp) - write(ndiag,*) 'harvest from: ',trim(mksrf_fhrvtyp) - write(ndiag,*) 'fmax from: ',trim(mksrf_fmax) - write(ndiag,*) 'glaciers from: ',trim(mksrf_fglacier) - write(ndiag,*) ' with: ', nglcec, ' glacier elevation classes' - write(ndiag,*) 'glacier region ID from: ',trim(mksrf_fglacierregion) - write(ndiag,*) 'urban topography from: ',trim(mksrf_furbtopo) - write(ndiag,*) 'urban from: ',trim(mksrf_furban) - write(ndiag,*) 'inland lake from: ',trim(mksrf_flakwat) - write(ndiag,*) 'inland wetland from: ',trim(mksrf_fwetlnd) - write(ndiag,*) 'soil texture from: ',trim(mksrf_fsoitex) - write(ndiag,*) 'soil organic from: ',trim(mksrf_forganic) - write(ndiag,*) 'soil color from: ',trim(mksrf_fsoicol) - write(ndiag,*) 'VOC emission factors from: ',trim(mksrf_fvocef) - write(ndiag,*) 'gdp from: ',trim(mksrf_fgdp) - write(ndiag,*) 'peat from: ',trim(mksrf_fpeat) - write(ndiag,*) 'soil depth from: ',trim(mksrf_fsoildepth) - write(ndiag,*) 'abm from: ',trim(mksrf_fabm) - write(ndiag,*) 'topography statistics from: ',trim(mksrf_ftopostats) - write(ndiag,*) 'VIC parameters from: ',trim(mksrf_fvic) - write(ndiag,*)' mapping for pft ',trim(map_fpft) - write(ndiag,*)' mapping for lake water ',trim(map_flakwat) - write(ndiag,*)' mapping for wetland ',trim(map_fwetlnd) - write(ndiag,*)' mapping for glacier ',trim(map_fglacier) - write(ndiag,*)' mapping for glacier region ',trim(map_fglacierregion) - write(ndiag,*)' mapping for soil texture ',trim(map_fsoitex) - write(ndiag,*)' mapping for soil color ',trim(map_fsoicol) - write(ndiag,*)' mapping for soil organic ',trim(map_forganic) - write(ndiag,*)' mapping for urban ',trim(map_furban) - write(ndiag,*)' mapping for fmax ',trim(map_fmax) - write(ndiag,*)' mapping for VOC pct emis ',trim(map_fvocef) - write(ndiag,*)' mapping for harvest ',trim(map_fharvest) - write(ndiag,*)' mapping for lai/sai ',trim(map_flai) - write(ndiag,*)' mapping for urb topography ',trim(map_furbtopo) - write(ndiag,*)' mapping for GDP ',trim(map_fgdp) - write(ndiag,*)' mapping for peatlands ',trim(map_fpeat) - write(ndiag,*)' mapping for soil depth ',trim(map_fsoildepth) - write(ndiag,*)' mapping for ag fire pk month ',trim(map_fabm) - write(ndiag,*)' mapping for topography stats ',trim(map_ftopostats) - write(ndiag,*)' mapping for VIC parameters ',trim(map_fvic) - - if (mksrf_fdynuse /= ' ') then - write(6,*)'mksrf_fdynuse = ',trim(mksrf_fdynuse) - end if - - ! ---------------------------------------------------------------------- - ! Make surface dataset fields - ! ---------------------------------------------------------------------- - - ! Make PFTs [pctnatpft, pctcft] from dataset [fvegtyp] - - call mkpft(ldomain, mapfname=map_fpft, fpft=mksrf_fvegtyp, & - ndiag=ndiag, pctlnd_o=pctlnd_pft, pctnatpft_o=pctnatpft, pctcft_o=pctcft) - - ! Create harvesting data at model resolution - if (all_veg) then - ! In this case, we don't call mkharvest, so we want the harvest variables to be - ! initialized reasonably. - harvest_initval = 0._r8 - else - harvest_initval = spval - end if - call mkharvest_init( ns_o, harvest_initval, harvdata, mksrf_fhrvtyp ) - if ( .not. all_veg )then - - call mkharvest( ldomain, mapfname=map_fharvest, datfname=mksrf_fhrvtyp, & - ndiag=ndiag, harvdata=harvdata ) - end if - - ! Make inland water [pctlak, pctwet] [flakwat] [fwetlnd] - - call mklakwat (ldomain, mapfname=map_flakwat, datfname=mksrf_flakwat, & - ndiag=ndiag, zero_out=all_urban.or.all_veg, lake_o=pctlak) - - call mkwetlnd (ldomain, mapfname=map_fwetlnd, datfname=mksrf_fwetlnd, & - ndiag=ndiag, zero_out=all_urban.or.all_veg.or.no_inlandwet, swmp_o=pctwet) - - ! Make glacier fraction [pctgla] from [fglacier] dataset - - call mkglacier (ldomain, mapfname=map_fglacier, datfname=mksrf_fglacier, & - ndiag=ndiag, zero_out=all_urban.or.all_veg, glac_o=pctgla) - - ! Make glacier region ID [glacier_region] from [fglacierregion] dataset - - call mkglacierregion (ldomain, mapfname=map_fglacierregion, & - datfname=mksrf_fglacierregion, ndiag=ndiag, & - glacier_region_o = glacier_region) - - ! Make soil texture [pctsand, pctclay] [fsoitex] - - call mksoiltex (ldomain, mapfname=map_fsoitex, datfname=mksrf_fsoitex, & - ndiag=ndiag, sand_o=pctsand, clay_o=pctclay) - ! Make soil color classes [soicol] [fsoicol] - - call mksoilcol (ldomain, mapfname=map_fsoicol, datfname=mksrf_fsoicol, & - ndiag=ndiag, soil_color_o=soicol, nsoicol=nsoicol) - - ! Make fmax [fmax] from [fmax] dataset - - allocate(fmax(ns_o)) - fmax(:) = spval - call mkfmax (ldomain, mapfname=map_fmax, datfname=mksrf_fmax, & - ndiag=ndiag, fmax_o=fmax) - - ! Make GDP data [gdp] from [gdp] - - call mkgdp (ldomain, mapfname=map_fgdp, datfname=mksrf_fgdp, & - ndiag=ndiag, gdp_o=gdp) - - ! Make peat data [fpeat] from [peatf] - - call mkpeat (ldomain, mapfname=map_fpeat, datfname=mksrf_fpeat, & - ndiag=ndiag, peat_o=fpeat) - - ! Make soil depth data [soildepth] from [soildepthf] - - call mksoildepth (ldomain, mapfname=map_fsoildepth, datfname=mksrf_fsoildepth, & - ndiag=ndiag, soildepth_o=soildepth) - - ! Make agricultural fire peak month data [abm] from [abm] - - call mkagfirepkmon (ldomain, mapfname=map_fabm, datfname=mksrf_fabm, & - ndiag=ndiag, agfirepkmon_o=agfirepkmon) - - ! Make urban fraction [pcturb] from [furban] dataset - - call mkurban (ldomain, mapfname=map_furban, datfname=mksrf_furban, & - ndiag=ndiag, zero_out=all_veg, urbn_o=pcturb, urbn_classes_o=urbn_classes, & - region_o=urban_region) - - ! Make elevation [elev] from [ftopo, ffrac] dataset - ! Used only to screen pcturb - ! Screen pcturb by elevation threshold from elev dataset - - if ( .not. all_urban .and. .not. all_veg )then - allocate(elev(ns_o)) - elev(:) = spval - ! NOTE(wjs, 2016-01-15) This uses the 'TOPO_ICE' variable for historical reasons - ! (this same dataset used to be used for glacier-related purposes as well). - ! TODO(wjs, 2016-01-15) A better solution for this urban screening would probably - ! be to modify the raw urban data; in that case, I believe we could remove - ! furbtopo. - call mkelev (ldomain, mapfname=map_furbtopo, datfname=mksrf_furbtopo, & - varname='TOPO_ICE', ndiag=ndiag, elev_o=elev) - - where (elev .gt. elev_thresh) - pcturb = 0._r8 - end where - deallocate(elev) - end if - - ! Compute topography statistics [topo_stddev, slope] from [ftopostats] - call mktopostats (ldomain, mapfname=map_ftopostats, datfname=mksrf_ftopostats, & - ndiag=ndiag, topo_stddev_o=topo_stddev, slope_o=slope, std_elev=std_elev) - - ! Make VIC parameters [binfl, ws, dsmax, ds] from [fvic] - if ( outnc_vic )then - call mkVICparams (ldomain, mapfname=map_fvic, datfname=mksrf_fvic, ndiag=ndiag, & - binfl_o=vic_binfl, ws_o=vic_ws, dsmax_o=vic_dsmax, ds_o=vic_ds) - end if - - ! Make lake depth [lakedepth] from [flakwat] - call mklakparams (ldomain, mapfname=map_flakwat, datfname=mksrf_flakwat, ndiag=ndiag, & - lakedepth_o=lakedepth) - - ! Make organic matter density [organic] [forganic] - allocate (organic(ns_o,nlevsoi)) - organic(:,:) = spval - call mkorganic (ldomain, mapfname=map_forganic, datfname=mksrf_forganic, & - ndiag=ndiag, organic_o=organic) - - ! Make VOC emission factors for isoprene & - ! [ef1_btr,ef1_fet,ef1_fdt,ef1_shr,ef1_grs,ef1_crp] - - allocate ( ef1_btr(ns_o) , & - ef1_fet(ns_o) , & - ef1_fdt(ns_o) , & - ef1_shr(ns_o) , & - ef1_grs(ns_o) , & - ef1_crp(ns_o) ) - ef1_btr(:) = 0._r8 - ef1_fet(:) = 0._r8 - ef1_fdt(:) = 0._r8 - ef1_shr(:) = 0._r8 - ef1_grs(:) = 0._r8 - ef1_crp(:) = 0._r8 - - call mkvocef (ldomain, mapfname=map_fvocef, datfname=mksrf_fvocef, ndiag=ndiag, & - ef_btr_o=ef1_btr, ef_fet_o=ef1_fet, ef_fdt_o=ef1_fdt, & - ef_shr_o=ef1_shr, ef_grs_o=ef1_grs, ef_crp_o=ef1_crp) - - ! Do landuse changes such as for the poles, etc. - - call change_landuse( ldomain, dynpft=.false. ) - - do n = 1,ns_o - - ! Truncate all percentage fields on output grid. This is needed to - ! insure that wt is zero (not a very small number such as - ! 1e-16) where it really should be zero - - do k = 1,nlevsoi - pctsand(n,k) = float(nint(pctsand(n,k))) - pctclay(n,k) = float(nint(pctclay(n,k))) - end do - pctlak(n) = float(nint(pctlak(n))) - pctwet(n) = float(nint(pctwet(n))) - pctgla(n) = float(nint(pctgla(n))) - - ! Assume wetland, glacier and/or lake when dataset landmask implies ocean - ! (assume medium soil color (15) and loamy texture). - ! Also set pftdata_mask here - - if (pctlnd_pft(n) < 1.e-6_r8) then - pftdata_mask(n) = 0 - soicol(n) = 15 - if (pctgla(n) < 1.e-6_r8) then - pctwet(n) = 100._r8 - pctlak(n) - pctgla(n) = 0._r8 - else - pctwet(n) = max(100._r8 - pctgla(n) - pctlak(n), 0.0_r8) - end if - pcturb(n) = 0._r8 - call pctnatpft(n)%set_pct_l2g(0._r8) - call pctcft(n)%set_pct_l2g(0._r8) - pctsand(n,:) = 43._r8 - pctclay(n,:) = 18._r8 - organic(n,:) = 0._r8 - else - pftdata_mask(n) = 1 - end if - - ! Make sure sum of land cover types does not exceed 100. If it does, - ! subtract excess from most dominant land cover. - - suma = pctlak(n) + pctwet(n) + pcturb(n) + pctgla(n) - if (suma > 250._r4) then - write (6,*) subname, ' error: sum of pctlak, pctwet,', & - 'pcturb and pctgla is greater than 250%' - write (6,*)'n,pctlak,pctwet,pcturb,pctgla= ', & - n,pctlak(n),pctwet(n),pcturb(n),pctgla(n) - call abort() - else if (suma > 100._r4) then - pctlak(n) = pctlak(n) * 100._r8/suma - pctwet(n) = pctwet(n) * 100._r8/suma - pcturb(n) = pcturb(n) * 100._r8/suma - pctgla(n) = pctgla(n) * 100._r8/suma - end if - - end do - - call normalizencheck_landuse(ldomain) - - ! Write out sum of PFT's - - do k = natpft_lb,natpft_ub - suma = 0._r8 - do n = 1,ns_o - suma = suma + pctnatpft(n)%get_one_pct_p2g(k) - enddo - write(6,*) 'sum over domain of pft ',k,suma - enddo - write(6,*) - - do k = cft_lb,cft_ub - suma = 0._r8 - do n = 1,ns_o - suma = suma + pctcft(n)%get_one_pct_p2g(k) - enddo - write(6,*) 'sum over domain of cft ',k,suma - enddo - write(6,*) - - ! Make final values of percent urban by class - ! This call needs to occur after all corrections are made to pcturb - - call normalize_classes_by_gcell(urbn_classes, pcturb, urbn_classes_g) - - - ! Make glacier multiple elevation classes [pctglcmec,topoglcmec] from [fglacier] dataset - ! This call needs to occur after pctgla has been adjusted for the final time - - allocate (pctglcmec(ns_o,nglcec), & - topoglcmec(ns_o,nglcec) ) - if ( outnc_3dglc )then - allocate( & - pctglcmec_gic(ns_o,nglcec), & - pctglcmec_icesheet(ns_o,nglcec)) - allocate (pctglc_gic(ns_o)) - allocate (pctglc_icesheet(ns_o)) - end if - - pctglcmec(:,:) = spval - topoglcmec(:,:) = spval - - if ( outnc_3dglc )then - call mkglcmec (ldomain, mapfname=map_fglacier, & - datfname_fglacier=mksrf_fglacier, ndiag=ndiag, & - pctglcmec_o=pctglcmec, topoglcmec_o=topoglcmec, & - pctglcmec_gic_o=pctglcmec_gic, pctglcmec_icesheet_o=pctglcmec_icesheet, & - pctglc_gic_o=pctglc_gic, pctglc_icesheet_o=pctglc_icesheet) - else - call mkglcmec (ldomain, mapfname=map_fglacier, & - datfname_fglacier=mksrf_fglacier, ndiag=ndiag, & - pctglcmec_o=pctglcmec, topoglcmec_o=topoglcmec ) - end if - - ! Determine fractional land from pft dataset - - do n = 1,ns_o - landfrac_pft(n) = pctlnd_pft(n)/100._r8 - end do - - ! ---------------------------------------------------------------------- - ! Create surface dataset - ! ---------------------------------------------------------------------- - - ! Create netCDF surface dataset. - - ! If fsurdat is blank, then we do not write a surface dataset - but we may still - ! write a dynamic landuse file. This is useful if we are creating many datasets at - ! once, and don't want duplicate surface datasets. - ! - ! TODO(wjs, 2016-01-26) Ideally, we would also avoid doing the processing of - ! variables that are just needed by the surface dataset (not by the dynamic landuse - ! file). However, this would require some analysis of the above code, to determine - ! which processing is needed (directly or indirectly) in order to create a dynamic - ! landuse file. - - if (fsurdat /= ' ') then - - call mkfile(ldomain, trim(fsurdat), harvdata, dynlanduse = .false.) - - call domain_write(ldomain, fsurdat) - - call check_ret(nf_open(trim(fsurdat), nf_write, ncid), subname) - call check_ret(nf_set_fill (ncid, nf_nofill, omode), subname) - - ! Write fields OTHER THAN lai, sai, heights, and urban parameters to netcdf surface dataset - - call check_ret(nf_inq_varid(ncid, 'natpft', varid), subname) - call check_ret(nf_put_var_int(ncid, varid, (/(n,n=natpft_lb,natpft_ub)/)), subname) - - if (num_cft > 0) then - call check_ret(nf_inq_varid(ncid, 'cft', varid), subname) - call check_ret(nf_put_var_int(ncid, varid, (/(n,n=cft_lb,cft_ub)/)), subname) - end if - - call check_ret(nf_inq_varid(ncid, 'PFTDATA_MASK', varid), subname) - call check_ret(nf_put_var_int(ncid, varid, pftdata_mask), subname) - - call check_ret(nf_inq_varid(ncid, 'LANDFRAC_PFT', varid), subname) - call check_ret(nf_put_var_double(ncid, varid, landfrac_pft), subname) - - call check_ret(nf_inq_varid(ncid, 'mxsoil_color', varid), subname) - call check_ret(nf_put_var_int(ncid, varid, nsoicol), subname) - - call check_ret(nf_inq_varid(ncid, 'SOIL_COLOR', varid), subname) - call check_ret(nf_put_var_int(ncid, varid, soicol), subname) - - call check_ret(nf_inq_varid(ncid, 'PCT_SAND', varid), subname) - call check_ret(nf_put_var_double(ncid, varid, pctsand), subname) - - call check_ret(nf_inq_varid(ncid, 'PCT_CLAY', varid), subname) - call check_ret(nf_put_var_double(ncid, varid, pctclay), subname) - - call check_ret(nf_inq_varid(ncid, 'PCT_WETLAND', varid), subname) - call check_ret(nf_put_var_double(ncid, varid, pctwet), subname) - - call check_ret(nf_inq_varid(ncid, 'PCT_LAKE', varid), subname) - call check_ret(nf_put_var_double(ncid, varid, pctlak), subname) - - call check_ret(nf_inq_varid(ncid, 'PCT_GLACIER', varid), subname) - call check_ret(nf_put_var_double(ncid, varid, pctgla), subname) - - call check_ret(nf_inq_varid(ncid, 'GLACIER_REGION', varid), subname) - call check_ret(nf_put_var_int(ncid, varid, glacier_region), subname) - - call check_ret(nf_inq_varid(ncid, 'PCT_GLC_MEC', varid), subname) - call check_ret(nf_put_var_double(ncid, varid, pctglcmec), subname) - - call check_ret(nf_inq_varid(ncid, 'GLC_MEC', varid), subname) - call check_ret(nf_put_var_double(ncid, varid, elevclass), subname) - - call check_ret(nf_inq_varid(ncid, 'TOPO_GLC_MEC', varid), subname) - call check_ret(nf_put_var_double(ncid, varid, topoglcmec), subname) - - if ( outnc_3dglc )then - call check_ret(nf_inq_varid(ncid, 'PCT_GLC_MEC_GIC', varid), subname) - call check_ret(nf_put_var_double(ncid, varid, pctglcmec_gic), subname) - - call check_ret(nf_inq_varid(ncid, 'PCT_GLC_MEC_ICESHEET', varid), subname) - call check_ret(nf_put_var_double(ncid, varid, pctglcmec_icesheet), subname) - - call check_ret(nf_inq_varid(ncid, 'PCT_GLC_GIC', varid), subname) - call check_ret(nf_put_var_double(ncid, varid, pctglc_gic), subname) - - call check_ret(nf_inq_varid(ncid, 'PCT_GLC_ICESHEET', varid), subname) - call check_ret(nf_put_var_double(ncid, varid, pctglc_icesheet), subname) - end if - - if ( outnc_3dglc )then - call check_ret(nf_inq_varid(ncid, 'PCT_GLC_MEC_GIC', varid), subname) - call check_ret(nf_put_var_double(ncid, varid, pctglcmec_gic), subname) - - call check_ret(nf_inq_varid(ncid, 'PCT_GLC_MEC_ICESHEET', varid), subname) - call check_ret(nf_put_var_double(ncid, varid, pctglcmec_icesheet), subname) - - call check_ret(nf_inq_varid(ncid, 'PCT_GLC_GIC', varid), subname) - call check_ret(nf_put_var_double(ncid, varid, pctglc_gic), subname) - - call check_ret(nf_inq_varid(ncid, 'PCT_GLC_ICESHEET', varid), subname) - call check_ret(nf_put_var_double(ncid, varid, pctglc_icesheet), subname) - end if - - call check_ret(nf_inq_varid(ncid, 'PCT_URBAN', varid), subname) - call check_ret(nf_put_var_double(ncid, varid, urbn_classes_g), subname) - - call check_ret(nf_inq_varid(ncid, 'PCT_NATVEG', varid), subname) - call check_ret(nf_put_var_double(ncid, varid, get_pct_l2g_array(pctnatpft)), subname) - - call check_ret(nf_inq_varid(ncid, 'PCT_CROP', varid), subname) - call check_ret(nf_put_var_double(ncid, varid, get_pct_l2g_array(pctcft)), subname) - - call check_ret(nf_inq_varid(ncid, 'PCT_NAT_PFT', varid), subname) - call check_ret(nf_put_var_double(ncid, varid, get_pct_p2l_array(pctnatpft)), subname) - - if (num_cft > 0) then - call check_ret(nf_inq_varid(ncid, 'PCT_CFT', varid), subname) - call check_ret(nf_put_var_double(ncid, varid, get_pct_p2l_array(pctcft)), subname) - end if - - call harvdata%getFieldsIdx( harvind1D, harvind2D ) - do k = 1, harvdata%num1Dfields() - call check_ret(nf_inq_varid(ncid, trim(mkharvest_fieldname(harvind1D(k),constant=.true.)), varid), subname) - harvest1D => harvdata%get1DFieldPtr( harvind1D(k), output=.true. ) - call check_ret(nf_put_var_double(ncid, varid, harvest1D), subname) - end do - do k = 1, harvdata%num2Dfields() - call check_ret(nf_inq_varid(ncid, trim(mkharvest_fieldname(harvind2D(k),constant=.true.)), varid), subname) - harvest2D => harvdata%get2DFieldPtr( harvind2D(k), output=.true. ) - call check_ret(nf_put_var_double(ncid, varid, harvest2D), subname) - end do - deallocate( harvind1D, harvind2D ) - - call check_ret(nf_inq_varid(ncid, 'FMAX', varid), subname) - call check_ret(nf_put_var_double(ncid, varid, fmax), subname) - - call check_ret(nf_inq_varid(ncid, 'gdp', varid), subname) - call check_ret(nf_put_var_double(ncid, varid, gdp), subname) - - call check_ret(nf_inq_varid(ncid, 'peatf', varid), subname) - call check_ret(nf_put_var_double(ncid, varid, fpeat), subname) - - - ! call check_ret(nf_inq_varid(ncid, 'Avg_Depth_Median', varid), subname) - call check_ret(nf_inq_varid(ncid, 'zbedrock', varid), subname) - call check_ret(nf_put_var_double(ncid, varid, soildepth), subname) - - call check_ret(nf_inq_varid(ncid, 'abm', varid), subname) - call check_ret(nf_put_var_int(ncid, varid, agfirepkmon), subname) - - call check_ret(nf_inq_varid(ncid, 'SLOPE', varid), subname) - call check_ret(nf_put_var_double(ncid, varid, slope), subname) - - call check_ret(nf_inq_varid(ncid, 'STD_ELEV', varid), subname) - call check_ret(nf_put_var_double(ncid, varid, topo_stddev), subname) - - if ( outnc_vic )then - call check_ret(nf_inq_varid(ncid, 'binfl', varid), subname) - call check_ret(nf_put_var_double(ncid, varid, vic_binfl), subname) - - call check_ret(nf_inq_varid(ncid, 'Ws', varid), subname) - call check_ret(nf_put_var_double(ncid, varid, vic_ws), subname) - - call check_ret(nf_inq_varid(ncid, 'Dsmax', varid), subname) - call check_ret(nf_put_var_double(ncid, varid, vic_dsmax), subname) - - call check_ret(nf_inq_varid(ncid, 'Ds', varid), subname) - call check_ret(nf_put_var_double(ncid, varid, vic_ds), subname) - end if - - call check_ret(nf_inq_varid(ncid, 'LAKEDEPTH', varid), subname) - call check_ret(nf_put_var_double(ncid, varid, lakedepth), subname) - - call check_ret(nf_inq_varid(ncid, 'EF1_BTR', varid), subname) - call check_ret(nf_put_var_double(ncid, varid, ef1_btr), subname) - - call check_ret(nf_inq_varid(ncid, 'EF1_FET', varid), subname) - call check_ret(nf_put_var_double(ncid, varid, ef1_fet), subname) - - call check_ret(nf_inq_varid(ncid, 'EF1_FDT', varid), subname) - call check_ret(nf_put_var_double(ncid, varid, ef1_fdt), subname) - - call check_ret(nf_inq_varid(ncid, 'EF1_SHR', varid), subname) - call check_ret(nf_put_var_double(ncid, varid, ef1_shr), subname) - - call check_ret(nf_inq_varid(ncid, 'EF1_GRS', varid), subname) - call check_ret(nf_put_var_double(ncid, varid, ef1_grs), subname) - - call check_ret(nf_inq_varid(ncid, 'EF1_CRP', varid), subname) - call check_ret(nf_put_var_double(ncid, varid, ef1_crp), subname) - - call check_ret(nf_inq_varid(ncid, 'ORGANIC', varid), subname) - call check_ret(nf_put_var_double(ncid, varid, organic), subname) - - call check_ret(nf_inq_varid(ncid, 'URBAN_REGION_ID', varid), subname) - call check_ret(nf_put_var_int(ncid, varid, urban_region), subname) - - ! Synchronize the disk copy of a netCDF dataset with in-memory buffers - - call check_ret(nf_sync(ncid), subname) - - ! ---------------------------------------------------------------------- - ! Make Urban Parameters from raw input data and write to surface dataset - ! Write to netcdf file is done inside mkurbanpar routine - ! ---------------------------------------------------------------------- - - write(6,*)'calling mkurbanpar' - call mkurbanpar(datfname=mksrf_furban, ncido=ncid, region_o=urban_region, & - urbn_classes_gcell_o=urbn_classes_g, & - urban_skip_abort_on_invalid_data_check=urban_skip_abort_on_invalid_data_check) - - ! ---------------------------------------------------------------------- - ! Make LAI and SAI from 1/2 degree data and write to surface dataset - ! Write to netcdf file is done inside mklai routine - ! ---------------------------------------------------------------------- - - write(6,*)'calling mklai' - call mklai(ldomain, mapfname=map_flai, datfname=mksrf_flai, & - ndiag=ndiag, ncido=ncid ) - - ! Close surface dataset - - call check_ret(nf_close(ncid), subname) - - write (6,'(72a1)') ("-",n=1,60) - write (6,*)' land model surface data set successfully created for ', & - 'grid of size ',ns_o - - else ! fsurdat == ' ' - - write (6,*) 'fsurdat is blank: skipping writing surface dataset' - - end if ! if (fsurdat /= ' ') - - ! Deallocate arrays NOT needed for dynamic-pft section of code - - deallocate ( organic ) - deallocate ( ef1_btr, ef1_fet, ef1_fdt, ef1_shr, ef1_grs, ef1_crp ) - deallocate ( pctglcmec, topoglcmec) - if ( outnc_3dglc ) deallocate ( pctglc_gic, pctglc_icesheet) - deallocate ( elevclass ) - deallocate ( fmax ) - deallocate ( pctsand, pctclay ) - deallocate ( soicol ) - deallocate ( gdp, fpeat, agfirepkmon ) - deallocate ( soildepth ) - deallocate ( topo_stddev, slope ) - deallocate ( vic_binfl, vic_ws, vic_dsmax, vic_ds ) - deallocate ( lakedepth ) - deallocate ( glacier_region ) - - call harvdata%clean() - - ! ---------------------------------------------------------------------- - ! Create dynamic land use dataset if appropriate - ! ---------------------------------------------------------------------- - - if (mksrf_fdynuse /= ' ') then - - write(6,*)'creating dynamic land use dataset' - - allocate(pctlnd_pft_dyn(ns_o)) - call mkharvest_init( ns_o, spval, harvdata, mksrf_fhrvtyp ) - - if (fdyndat == ' ') then - write(6,*)' must specify fdyndat in namelist if mksrf_fdynuse is not blank' - call abort() - end if - - ! Define dimensions and global attributes - - call mkfile(ldomain, fdyndat, harvdata, dynlanduse=.true.) - - ! Write fields other pft to dynamic land use dataset - - call domain_write(ldomain, fdyndat) - - call check_ret(nf_open(trim(fdyndat), nf_write, ncid), subname) - call check_ret(nf_set_fill (ncid, nf_nofill, omode), subname) - - call check_ret(nf_inq_varid(ncid, 'natpft', varid), subname) - call check_ret(nf_put_var_int(ncid, varid, (/(n,n=natpft_lb,natpft_ub)/)), subname) - - if (num_cft > 0) then - call check_ret(nf_inq_varid(ncid, 'cft', varid), subname) - call check_ret(nf_put_var_int(ncid, varid, (/(n,n=cft_lb,cft_ub)/)), subname) - end if - - call check_ret(nf_inq_varid(ncid, 'PFTDATA_MASK', varid), subname) - call check_ret(nf_put_var_int(ncid, varid, pftdata_mask), subname) - - call check_ret(nf_inq_varid(ncid, 'LANDFRAC_PFT', varid), subname) - call check_ret(nf_put_var_double(ncid, varid, landfrac_pft), subname) - - ! Synchronize the disk copy of a netCDF dataset with in-memory buffers - - call check_ret(nf_sync(ncid), subname) - - ! Read in each dynamic pft landuse dataset - - nfdyn = getavu(); call opnfil (mksrf_fdynuse, nfdyn, 'f') - - pctnatpft_max = pctnatpft - pctcft_max = pctcft - - ntim = 0 - do - ! Read input pft data - - read(nfdyn, '(A195,1x,I4)', iostat=ier) string, year - if (ier /= 0) exit - ! - ! If pft fraction override is set, than intrepret string as PFT and harvesting override values - ! - if ( all_veg )then - fname = ' ' - fhrvname = ' ' - call mkpft_parse_oride(string) - call mkharvest_parse_oride(string) - write(6, '(a, i4, a)') 'PFT and harvesting values for year ', year, ' :' - write(6, '(a, a)') ' ', trim(string) - ! - ! Otherwise intrepret string as a filename with PFT and harvesting values in it - ! - else - fname = string - write(6,*)'input pft dynamic dataset for year ', year, ' is : ', trim(fname) - read(nfdyn, '(A195,1x,I4)', iostat=ier) fhrvname, year2 - if ( year2 /= year ) then - write(6,*) subname, ' error: year for harvest not equal to year for PFT files' - call abort() - end if - end if - ntim = ntim + 1 - - ! Create pctpft data at model resolution - - call mkpft(ldomain, mapfname=map_fpft, fpft=fname, & - ndiag=ndiag, pctlnd_o=pctlnd_pft_dyn, pctnatpft_o=pctnatpft, pctcft_o=pctcft ) - - ! Create harvesting data at model resolution - - call mkharvest( ldomain, mapfname=map_fharvest, datfname=fhrvname, & - ndiag=ndiag, harvdata=harvdata ) - - ! Consistency check on input land fraction - - do n = 1,ns_o - if (pctlnd_pft_dyn(n) /= pctlnd_pft(n)) then - write(6,*) subname,' error: pctlnd_pft for dynamics data = ',& - pctlnd_pft_dyn(n), ' not equal to pctlnd_pft for surface data = ',& - pctlnd_pft(n),' at n= ',n - if ( trim(fname) == ' ' )then - write(6,*) ' PFT string = ', string - else - write(6,*) ' PFT file = ', fname - end if - call abort() - end if - end do - - call change_landuse(ldomain, dynpft=.true.) - - call normalizencheck_landuse(ldomain) - - call update_max_array(pctnatpft_max,pctnatpft) - call update_max_array(pctcft_max,pctcft) - - ! Output time-varying data for current year - - call check_ret(nf_inq_varid(ncid, 'PCT_NAT_PFT', varid), subname) - call ncd_put_time_slice(ncid, varid, ntim, get_pct_p2l_array(pctnatpft)) - - call check_ret(nf_inq_varid(ncid, 'PCT_CROP', varid), subname) - call ncd_put_time_slice(ncid, varid, ntim, get_pct_l2g_array(pctcft)) - - if (num_cft > 0) then - call check_ret(nf_inq_varid(ncid, 'PCT_CFT', varid), subname) - call ncd_put_time_slice(ncid, varid, ntim, get_pct_p2l_array(pctcft)) - end if - - call harvdata%getFieldsIdx( harvind1D, harvind2D ) - do k = 1, harvdata%num1Dfields() - call check_ret(nf_inq_varid(ncid, trim(mkharvest_fieldname(harvind1D(k),constant=.false.)), varid), subname) - harvest1D => harvdata%get1DFieldPtr( harvind1D(k), output=.true. ) - call ncd_put_time_slice(ncid, varid, ntim, harvest1D) - end do - do k = 1, harvdata%num2Dfields() - call check_ret(nf_inq_varid(ncid, trim(mkharvest_fieldname(harvind2D(k),constant=.false.)), varid), subname) - harvest2D => harvdata%get2DFieldPtr( harvind2D(k), output=.true. ) - call ncd_put_time_slice(ncid, varid, ntim, harvest2D) - end do - deallocate( harvind1D, harvind2D ) - - call check_ret(nf_inq_varid(ncid, 'YEAR', varid), subname) - call check_ret(nf_put_vara_int(ncid, varid, ntim, 1, year), subname) - - call check_ret(nf_inq_varid(ncid, 'time', varid), subname) - call check_ret(nf_put_vara_int(ncid, varid, ntim, 1, year), subname) - - call check_ret(nf_inq_varid(ncid, 'input_pftdata_filename', varid), subname) - call check_ret(nf_put_vara_text(ncid, varid, (/ 1, ntim /), (/ len_trim(string), 1 /), trim(string) ), subname) - - ! Synchronize the disk copy of a netCDF dataset with in-memory buffers - - call check_ret(nf_sync(ncid), subname) - - end do ! end of read loop - - call check_ret(nf_inq_varid(ncid, 'PCT_NAT_PFT_MAX', varid), subname) - call check_ret(nf_put_var_double(ncid, varid, get_pct_p2l_array(pctnatpft_max)), subname) - - call check_ret(nf_inq_varid(ncid, 'PCT_CROP_MAX', varid), subname) - call check_ret(nf_put_var_double(ncid, varid, get_pct_l2g_array(pctcft_max)), subname) - - if (num_cft > 0) then - call check_ret(nf_inq_varid(ncid, 'PCT_CFT_MAX', varid), subname) - call check_ret(nf_put_var_double(ncid, varid, get_pct_p2l_array(pctcft_max)), subname) - end if - - call check_ret(nf_close(ncid), subname) - - end if ! end of if-create dynamic landust dataset - - ! ---------------------------------------------------------------------- - ! Close diagnostic dataset - ! ---------------------------------------------------------------------- - - close (ndiag) - write (6,*) - write (6,*) 'Surface data output file = ',trim(fsurdat) - write (6,*) ' This file contains the land model surface data' - write (6,*) 'Diagnostic log file = ',trim(fsurlog) - write (6,*) ' See this file for a summary of the dataset' - write (6,*) - - write (6,*) 'Successfully created surface dataset' - -!----------------------------------------------------------------------- -contains -!----------------------------------------------------------------------- - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: change_landuse -! -! !INTERFACE: -subroutine change_landuse( ldomain, dynpft ) -! -! !DESCRIPTION: -! -! Do landuse changes such as for the poles, etc. -! -! !USES: - implicit none -! -! !ARGUMENTS: - type(domain_type) :: ldomain - logical, intent(in) :: dynpft ! if part of the dynpft section of code - -! -! !REVISION HISTORY: -! 9/10/09: Erik Kluzek spin off subroutine from original embedded code -! -!EOP -! -! !LOCAL VARIABLES: - integer :: n,ns_o ! indices - character(len=32) :: subname = 'change_landuse' ! subroutine name -!----------------------------------------------------------------------- - - ns_o = ldomain%ns - do n = 1,ns_o - - ! If have pole points on grid - set south pole to glacier - ! north pole is assumed as non-land - - if (abs((ldomain%latc(n) - 90._r8)) < 1.e-6_r8) then - pctlak(n) = 0._r8 - pctwet(n) = 0._r8 - pcturb(n) = 0._r8 - pctgla(n) = 100._r8 - call pctnatpft(n)%set_pct_l2g(0._r8) - call pctcft(n)%set_pct_l2g(0._r8) - if ( .not. dynpft )then - organic(n,:) = 0._r8 - ef1_btr(n) = 0._r8 - ef1_fet(n) = 0._r8 - ef1_fdt(n) = 0._r8 - ef1_shr(n) = 0._r8 - ef1_grs(n) = 0._r8 - ef1_crp(n) = 0._r8 - end if - end if - - end do - -end subroutine change_landuse - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: normalizencheck_landuse -! -! !INTERFACE: -subroutine normalizencheck_landuse(ldomain) -! -! !DESCRIPTION: -! -! Normalize land use and make sure things add up to 100% as well as -! checking that things are as they should be. -! -! Precondition: pctlak + pctwet + pcturb + pctgla <= 100 (within roundoff) -! -! !USES: - use mkpftConstantsMod , only : baregroundindex - use mkpftUtilsMod , only : adjust_total_veg_area - implicit none -! !ARGUMENTS: - type(domain_type) :: ldomain -! -! !REVISION HISTORY: -! 9/10/09: Erik Kluzek spin off subroutine from original embedded code -! -!EOP -! -! !LOCAL VARIABLES: - integer :: m,k,n,ns_o ! indices - integer :: nsmall ! number of small PFT values for a single check - integer :: nsmall_tot ! total number of small PFT values in all grid cells - real(r8) :: suma ! sum for error check - real(r8) :: suma2 ! another sum for error check - real(r8) :: new_total_veg_pct ! new % veg (% of grid cell, total of natural veg & crop) - real(r8) :: bare_pct_p2g ! % of bare soil, as % of grid cell - real(r8) :: bare_urb_diff ! difference between bare soil and urban % - real(r8) :: pcturb_excess ! excess urban % not accounted for by bare soil - real(r8) :: sum8, sum8a ! sum for error check - real(r4) :: sum4a ! sum for error check - real(r8), parameter :: tol_loose = 1.e-4_r8 ! tolerance for some 'loose' error checks - real(r8), parameter :: toosmallPFT = 1.e-10_r8 ! tolerance for PFT's to ignore - character(len=32) :: subname = 'normalizencheck_landuse' ! subroutine name -!----------------------------------------------------------------------- - - ! ------------------------------------------------------------------------ - ! Normalize vegetated area so that vegetated + special area is 100% - ! ------------------------------------------------------------------------ - - ns_o = ldomain%ns - do n = 1,ns_o - - ! Check preconditions - if ( pctlak(n) < 0.0_r8 )then - write(6,*) subname, ' ERROR: pctlak is negative!' - write(6,*) 'n, pctlak = ', n, pctlak(n) - call abort() - end if - if ( pctwet(n) < 0.0_r8 )then - write(6,*) subname, ' ERROR: pctwet is negative!' - write(6,*) 'n, pctwet = ', n, pctwet(n) - call abort() - end if - if ( pcturb(n) < 0.0_r8 )then - write(6,*) subname, ' ERROR: pcturb is negative!' - write(6,*) 'n, pcturb = ', n, pcturb(n) - call abort() - end if - if ( pctgla(n) < 0.0_r8 )then - write(6,*) subname, ' ERROR: pctgla is negative!' - write(6,*) 'n, pctgla = ', n, pctgla(n) - call abort() - end if - - suma = pctlak(n) + pctwet(n) + pcturb(n) + pctgla(n) - if (suma > (100._r8 + tol_loose)) then - write(6,*) subname, ' ERROR: pctlak + pctwet + pcturb + pctgla must be' - write(6,*) '<= 100% before calling this subroutine' - write(6,*) 'n, pctlak, pctwet, pcturb, pctgla = ', & - n, pctlak(n), pctwet(n), pcturb(n), pctgla(n) - call abort() - end if - - ! First normalize vegetated (natural veg + crop) cover so that the total of - ! (vegetated + (special excluding urban)) is 100%. We'll deal with urban later. - ! - ! Note that, in practice, the total area of natural veg + crop is typically 100% - ! going into this routine. However, the following code does NOT rely on this, and - ! will work properly regardless of the initial area of natural veg + crop (even if - ! that initial area is 0%). - - suma = pctlak(n)+pctwet(n)+pctgla(n) - new_total_veg_pct = 100._r8 - suma - ! correct for rounding error: - new_total_veg_pct = max(new_total_veg_pct, 0._r8) - - call adjust_total_veg_area(new_total_veg_pct, pctnatpft=pctnatpft(n), pctcft=pctcft(n)) - - ! Make sure we did the above rescaling correctly - - suma = suma + pctnatpft(n)%get_pct_l2g() + pctcft(n)%get_pct_l2g() - if (abs(suma - 100._r8) > tol_loose) then - write(6,*) subname, ' ERROR in rescaling veg based on (special excluding urban' - write(6,*) 'suma = ', suma - call abort() - end if - - ! Now decrease the vegetated area to account for urban area. Urban needs to be - ! handled specially because we replace bare soil preferentially with urban, rather - ! than rescaling all PFTs equally. - - if (pcturb(n) > 0._r8) then - - ! Replace bare soil preferentially with urban - bare_pct_p2g = pctnatpft(n)%get_one_pct_p2g(baregroundindex) - bare_urb_diff = bare_pct_p2g - pcturb(n) - bare_pct_p2g = max(0._r8, bare_urb_diff) - call pctnatpft(n)%set_one_pct_p2g(baregroundindex, bare_pct_p2g) - pcturb_excess = abs(min(0._r8,bare_urb_diff)) - - ! For any urban not accounted for by bare soil, replace other PFTs - ! proportionally - if (pcturb_excess > 0._r8) then - ! Note that, in this case, we will have already reduced bare ground to 0% - - new_total_veg_pct = pctnatpft(n)%get_pct_l2g() + pctcft(n)%get_pct_l2g() - pcturb_excess - if (new_total_veg_pct < 0._r8) then - if (abs(new_total_veg_pct) < tol_loose) then - ! only slightly less than 0; correct it - new_total_veg_pct = 0._r8 - else - write(6,*) subname, ' ERROR: trying to replace veg with urban,' - write(6,*) 'but pcturb_excess exceeds current vegetation percent' - call abort() - end if - end if - - call adjust_total_veg_area(new_total_veg_pct, pctnatpft=pctnatpft(n), pctcft=pctcft(n)) - end if - - end if ! pcturb(n) > 0 - - ! Confirm that we have done the rescaling correctly: now the sum of all landunits - ! should be 100% - suma = pctlak(n)+pctwet(n)+pctgla(n)+pcturb(n) - suma = suma + pctnatpft(n)%get_pct_l2g() + pctcft(n)%get_pct_l2g() - if (abs(suma - 100._r8) > tol_loose) then - write(6,*) subname, ' ERROR: landunits do not sum to 100%' - write(6,*) 'n, suma, pctlak, pctwet, pctgla, pcturb, pctnatveg, pctcrop = ' - write(6,*) n, suma, pctlak(n), pctwet(n), pctgla(n), pcturb(n), & - pctnatpft(n)%get_pct_l2g(), pctcft(n)%get_pct_l2g() - call abort() - end if - - end do - - ! ------------------------------------------------------------------------ - ! Do other corrections and error checks - ! ------------------------------------------------------------------------ - - nsmall_tot = 0 - - do n = 1,ns_o - - ! If the coverage of any PFT or CFT is too small at the gridcell level, set its - ! % cover to 0, then renormalize everything else as needed - call pctnatpft(n)%remove_small_cover(toosmallPFT, nsmall) - nsmall_tot = nsmall_tot + nsmall - call pctcft(n)%remove_small_cover(toosmallPFT, nsmall) - nsmall_tot = nsmall_tot + nsmall - - suma = pctlak(n) + pctwet(n) + pcturb(n) + pctgla(n) - suma = suma + pctnatpft(n)%get_pct_l2g() + pctcft(n)%get_pct_l2g() - if ( abs(suma - 100.0_r8) > 2.0*epsilon(suma) )then - pctlak(n) = pctlak(n) * 100._r8/suma - pctwet(n) = pctwet(n) * 100._r8/suma - pcturb(n) = pcturb(n) * 100._r8/suma - pctgla(n) = pctgla(n) * 100._r8/suma - call pctnatpft(n)%set_pct_l2g(pctnatpft(n)%get_pct_l2g() * 100._r8/suma) - call pctcft(n)%set_pct_l2g(pctcft(n)%get_pct_l2g() * 100._r8/suma) - end if - - ! Roundoff error fix - suma = pctlak(n) + pctwet(n) + pcturb(n) + pctgla(n) - suma2 = pctnatpft(n)%get_pct_l2g() + pctcft(n)%get_pct_l2g() - if ( (suma < 100._r8 .and. suma > (100._r8 - 1.e-6_r8)) .or. & - (suma2 > 0.0_r8 .and. suma2 < 1.e-6_r8) ) then - write (6,*) 'Special land units near 100%, but not quite for n,suma =',n,suma - write (6,*) 'Adjusting special land units to 100%' - if (pctlak(n) >= 25._r8) then - pctlak(n) = 100._r8 - (pctwet(n) + pcturb(n) + pctgla(n)) - else if (pctwet(n) >= 25._r8) then - pctwet(n) = 100._r8 - (pctlak(n) + pcturb(n) + pctgla(n)) - else if (pcturb(n) >= 25._r8) then - pcturb(n) = 100._r8 - (pctlak(n) + pctwet(n) + pctgla(n)) - else if (pctgla(n) >= 25._r8) then - pctgla(n) = 100._r8 - (pctlak(n) + pctwet(n) + pcturb(n)) - else - write (6,*) subname, 'Error: sum of special land units nearly 100% but none is >= 25% at ', & - 'n,pctlak(n),pctwet(n),pcturb(n),pctgla(n),pctnatveg(n),pctcrop(n),suma = ', & - n,pctlak(n),pctwet(n),pcturb(n),pctgla(n),& - pctnatpft(n)%get_pct_l2g(),pctcft(n)%get_pct_l2g(),suma - call abort() - end if - call pctnatpft(n)%set_pct_l2g(0._r8) - call pctcft(n)%set_pct_l2g(0._r8) - end if - if ( any(pctnatpft(n)%get_pct_p2g() > 0.0_r8 .and. pctnatpft(n)%get_pct_p2g() < toosmallPFT ) .or. & - any(pctcft(n)%get_pct_p2g() > 0.0_r8 .and. pctcft(n)%get_pct_p2g() < toosmallPFT )) then - write (6,*) 'pctnatpft or pctcft is small at n=', n - write (6,*) 'pctnatpft%pct_p2l = ', pctnatpft(n)%get_pct_p2l() - write (6,*) 'pctcft%pct_p2l = ', pctcft(n)%get_pct_p2l() - write (6,*) 'pctnatpft%pct_l2g = ', pctnatpft(n)%get_pct_l2g() - write (6,*) 'pctcft%pct_l2g = ', pctcft(n)%get_pct_l2g() - call abort() - end if - - suma = pctlak(n) + pctwet(n) + pcturb(n) + pctgla(n) - if (suma < 100._r8-epsilon(suma) .and. suma > (100._r8 - 4._r8*epsilon(suma))) then - write (6,*) subname, 'n,pctlak,pctwet,pcturb,pctgla,pctnatveg,pctcrop= ', & - n,pctlak(n),pctwet(n),pcturb(n),pctgla(n),& - pctnatpft(n)%get_pct_l2g(), pctcft(n)%get_pct_l2g() - call abort() - end if - suma = suma + pctnatpft(n)%get_pct_l2g() + pctcft(n)%get_pct_l2g() - if ( abs(suma-100._r8) > 1.e-10_r8) then - write (6,*) subname, ' error: sum of pctlak, pctwet,', & - 'pcturb, pctgla, pctnatveg and pctcrop is NOT equal to 100' - write (6,*)'n,pctlak,pctwet,pcturb,pctgla,pctnatveg,pctcrop,sum= ', & - n,pctlak(n),pctwet(n),pcturb(n),pctgla(n),& - pctnatpft(n)%get_pct_l2g(),pctcft(n)%get_pct_l2g(), suma - call abort() - end if - - end do - - ! Check that when pctnatveg+pctcrop identically zero, sum of special landunits is identically 100% - - if ( .not. outnc_double )then - do n = 1,ns_o - sum8 = real(pctlak(n),r4) - sum8 = sum8 + real(pctwet(n),r4) - sum8 = sum8 + real(pcturb(n),r4) - sum8 = sum8 + real(pctgla(n),r4) - sum4a = real(pctnatpft(n)%get_pct_l2g(),r4) - sum4a = sum4a + real(pctcft(n)%get_pct_l2g(),r4) - if ( sum4a==0.0_r4 .and. sum8 < 100._r4-2._r4*epsilon(sum4a) )then - write (6,*) subname, ' error: sum of pctlak, pctwet,', & - 'pcturb, pctgla is < 100% when pctnatveg+pctcrop==0 sum = ', sum8 - write (6,*)'n,pctlak,pctwet,pcturb,pctgla,pctnatveg,pctcrop= ', & - n,pctlak(n),pctwet(n),pcturb(n),pctgla(n), & - pctnatpft(n)%get_pct_l2g(),pctcft(n)%get_pct_l2g() - call abort() - end if - end do - else - do n = 1,ns_o - sum8 = pctlak(n) - sum8 = sum8 + pctwet(n) - sum8 = sum8 + pcturb(n) - sum8 = sum8 + pctgla(n) - sum8a = pctnatpft(n)%get_pct_l2g() - sum8a = sum8a + pctcft(n)%get_pct_l2g() - if ( sum8a==0._r8 .and. sum8 < (100._r8-4._r8*epsilon(sum8)) )then - write (6,*) subname, ' error: sum of pctlak, pctwet,', & - 'pcturb, pctgla is < 100% when pctnatveg+pctcrop==0 sum = ', sum8 - write (6,*) 'Total error, error/epsilon = ',100._r8-sum8, ((100._r8-sum8)/epsilon(sum8)) - write (6,*)'n,pctlak,pctwet,pcturb,pctgla,pctnatveg,pctcrop,epsilon= ', & - n,pctlak(n),pctwet(n),pcturb(n),pctgla(n),& - pctnatpft(n)%get_pct_l2g(),pctcft(n)%get_pct_l2g(), epsilon(sum8) - call abort() - end if - end do - end if - - ! Make sure that there is no vegetation outside the pft mask - do n = 1,ns_o - if (pftdata_mask(n) == 0 .and. (pctnatpft(n)%get_pct_l2g() > 0 .or. pctcft(n)%get_pct_l2g() > 0)) then - write (6,*)'vegetation found outside the pft mask at n=',n - write (6,*)'pctnatveg,pctcrop=', pctnatpft(n)%get_pct_l2g(), pctcft(n)%get_pct_l2g() - call abort() - end if - end do - - ! Make sure that sums at the landunit level all add to 100% - ! (Note that we don't check pctglcmec here, because it isn't computed at the point - ! that this subroutine is called -- but the check of sum(pctglcmec) is done in - ! mkglcmecMod) - ! (Also note that we don't need to check pctnatpft or pctcft, because a similar check - ! is done internally by the pct_pft_type routines.) - do n = 1,ns_o - if (abs(sum(urbn_classes(n,:)) - 100._r8) > 1.e-12_r8) then - write(6,*) 'sum(urbn_classes(n,:)) != 100: ', n, sum(urbn_classes(n,:)) - call abort() - end if - end do - - if ( nsmall_tot > 0 )then - write (6,*)'number of small pft = ', nsmall_tot - end if - -end subroutine normalizencheck_landuse - -end program mksurfdat diff --git a/tools/mksurfdata_map/src/mktopostatsMod.F90 b/tools/mksurfdata_map/src/mktopostatsMod.F90 deleted file mode 100644 index 7e102d9bcf..0000000000 --- a/tools/mksurfdata_map/src/mktopostatsMod.F90 +++ /dev/null @@ -1,183 +0,0 @@ -module mktopostatsMod - -!----------------------------------------------------------------------- -!BOP -! -! !MODULE: mktopostatsMod -! -! !DESCRIPTION: -! make various topography statistics -! -! !REVISION HISTORY: -! Author: Bill Sacks -! -!----------------------------------------------------------------------- -! -! !USES: - use shr_kind_mod, only : r8 => shr_kind_r8 - use shr_sys_mod , only : shr_sys_flush - use mkdomainMod , only : domain_checksame - - implicit none - - private - -! !PUBLIC MEMBER FUNCTIONS: - public mktopostats ! make topo stddev & mean slope -! -!EOP -!=============================================================== -contains -!=============================================================== - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: mktopostats -! -! !INTERFACE: -subroutine mktopostats(ldomain, mapfname, datfname, ndiag, topo_stddev_o, slope_o, std_elev) -! -! !DESCRIPTION: -! make various topography statistics -! -! !USES: - use mkdomainMod, only : domain_type, domain_clean, domain_read - use mkgridmapMod - use mkncdio - use mkdiagnosticsMod, only : output_diagnostics_continuous, output_diagnostics_continuous_outonly - use mkchecksMod, only : min_bad, max_bad -! -! !ARGUMENTS: - - implicit none - type(domain_type) , intent(in) :: ldomain - character(len=*) , intent(in) :: mapfname ! input mapping file name - character(len=*) , intent(in) :: datfname ! input data file name - integer , intent(in) :: ndiag ! unit number for diag out - real(r8) , intent(in) :: std_elev ! standard deviation of elevation (m) to use when not using input file - real(r8) , intent(out):: topo_stddev_o(:) ! output grid: standard deviation of elevation (m) - real(r8) , intent(out):: slope_o(:) ! output grid: slope (degrees) -! -! !CALLED FROM: -! subroutine mksrfdat in module mksrfdatMod -! -! !REVISION HISTORY: -! Author: Bill Sacks -! -! -! !LOCAL VARIABLES: -!EOP - type(gridmap_type) :: tgridmap - type(domain_type) :: tdomain ! local domain - real(r8), allocatable :: data_i(:) ! data on input grid - integer :: ncid,varid ! input netCDF id's - integer :: ier ! error status - logical :: bypass_reading ! If should bypass reading dataset and just use a global value - - real(r8), parameter :: min_valid_topo_stddev = 0._r8 - - real(r8), parameter :: min_valid_slope = 0._r8 - real(r8), parameter :: max_valid_slope = 90._r8 - - character(len=32) :: subname = 'mktopostats' -!----------------------------------------------------------------------- - - write (6,*) 'Attempting to make Topography statistics.....' - if ( std_elev >= 0.0_r8 )then - bypass_reading = .true. - write (6,*) ' By pass the reading and just use global values' - else - bypass_reading = .false. - end if - call shr_sys_flush(6) - - ! ----------------------------------------------------------------- - ! Read domain and mapping information, check for consistency - ! ----------------------------------------------------------------- - - if ( .not. bypass_reading )then - call domain_read(tdomain,datfname) - - call gridmap_mapread(tgridmap, mapfname ) - - call gridmap_check( tgridmap, tgridmap%frac_src, tgridmap%frac_dst, subname ) - - call domain_checksame( tdomain, ldomain, tgridmap ) - - ! ----------------------------------------------------------------- - ! Open input file, allocate memory for input data - ! ----------------------------------------------------------------- - - write(6,*)'Open Topography file: ', trim(datfname) - call check_ret(nf_open(datfname, 0, ncid), subname) - - allocate(data_i(tdomain%ns), stat=ier) - if (ier/=0) call abort() - - ! ----------------------------------------------------------------- - ! Make topography standard deviation - ! ----------------------------------------------------------------- - - call check_ret(nf_inq_varid (ncid, 'ELEVATION', varid), subname) - call check_ret(nf_get_var_double (ncid, varid, data_i), subname) - call gridmap_areastddev(tgridmap, data_i, topo_stddev_o, nodata=0._r8) - - call output_diagnostics_continuous_outonly(topo_stddev_o, tgridmap, "Topo Std Dev", "m", ndiag) - else - write (6,*) ' Set std deviation of topography to ', std_elev - topo_stddev_o = std_elev - end if - - ! Check validity of output data - if (min_bad(topo_stddev_o, min_valid_topo_stddev, 'topo_stddev')) then - call abort() - end if - - - ! ----------------------------------------------------------------- - ! Regrid slope - ! ----------------------------------------------------------------- - - if ( .not. bypass_reading )then - call check_ret(nf_inq_varid (ncid, 'SLOPE', varid), subname) - call check_ret(nf_get_var_double (ncid, varid, data_i), subname) - - ! Subr. gridmap_areaave_no_srcmask should NOT be used in general. We have - ! kept it to support the rare raw data files for which we have masking on - ! the mapping file and, therefore, we do not explicitly pass the src_mask - ! as an argument. In general, users are advised to use subroutine - ! gridmap_areaave_srcmask. - call gridmap_areaave_no_srcmask(tgridmap, data_i, slope_o, nodata=0._r8) - - call output_diagnostics_continuous(data_i, slope_o, tgridmap, "Slope", "degrees", ndiag, tdomain%mask, tgridmap%frac_dst) - else - write (6,*) ' Set slope of topography to ', 0.0_r8 - slope_o = 0.0_r8 - end if - ! Check validity of output data - if (min_bad(slope_o, min_valid_slope, 'slope') .or. & - max_bad(slope_o, max_valid_slope, 'slope')) then - call abort() - end if - - - ! ----------------------------------------------------------------- - ! Close files and deallocate dynamic memory - ! ----------------------------------------------------------------- - - if ( .not. bypass_reading )then - call check_ret(nf_close(ncid), subname) - call domain_clean(tdomain) - call gridmap_clean(tgridmap) - deallocate (data_i) - end if - - write (6,*) 'Successfully made Topography statistics' - write (6,*) - call shr_sys_flush(6) - -end subroutine mktopostats - - -end module mktopostatsMod diff --git a/tools/mksurfdata_map/src/mkurbanparCommonMod.F90 b/tools/mksurfdata_map/src/mkurbanparCommonMod.F90 deleted file mode 100644 index ab738ea03c..0000000000 --- a/tools/mksurfdata_map/src/mkurbanparCommonMod.F90 +++ /dev/null @@ -1,365 +0,0 @@ -module mkurbanparCommonMod -!----------------------------------------------------------------------- -!BOP -! -! !MODULE: mkurbanparCommon -! -! !DESCRIPTION: -! Common routines for making urban parameter data, independent of the method used for -! making the urban parameters (e.g., averages, dominant type, etc.) -! -! (WJS 4-18-12: In the past, this contained routines shared between mkurbanparDomMod and -! mkurbanparAvgMod; now there is just a single module, mkurbanparMod, but I am keeping the -! separate mkurbanparCommonMod in case a similar split comes back in the future. However, -! if such a split seems unlikely in the future, these routines could be moved back into -! mkurbanparMod.) -! -! !REVISION HISTORY: -! Author: Bill Sacks -! -!----------------------------------------------------------------------- -! !USES: - use shr_kind_mod, only : r8 => shr_kind_r8 - use shr_sys_mod , only : shr_sys_flush - implicit none - - private - -! !PUBLIC MEMBER FUNCTIONS: - public :: mkurban_pct ! Make output urban %, given input urban % - public :: mkurban_pct_diagnostics ! print diagnostics related to pct urban - public :: mkelev ! Get elevation to reduce urban for high elevation areas -! -! !PUBLIC DATA MEMBERS: -! - real(r8), parameter :: MIN_DENS = 0.1_r8 ! minimum urban density (% of grid cell) - below this value, urban % is set to 0 - - public :: MIN_DENS -! -!EOP - -contains - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: mkurban_pct -! -! !INTERFACE: -subroutine mkurban_pct(ldomain, tdomain, tgridmap, urbn_i, urbn_o, frac_dst) -! -! !DESCRIPTION: -! make percent urban on output grid, given percent urban on input grid -! -! This assumes that we're neither using all_urban or zero_out -! -! -! !USES: - use mkdomainMod , only : domain_type, domain_checksame - use mkgridmapMod - use mkvarctl , only : mksrf_gridtype -! -! !ARGUMENTS: - implicit none - type(domain_type) , intent(in) :: ldomain - type(domain_type) , intent(in) :: tdomain ! local domain - type(gridmap_type), intent(in) :: tgridmap ! local gridmap - real(r8) , intent(in) :: urbn_i(:) ! input grid: percent urban - real(r8) , intent(in) :: frac_dst(:) ! output fractions - real(r8) , intent(out):: urbn_o(:) ! output grid: percent urban -! -! !REVISION HISTORY: -! Author: Bill Sacks -! (Moved from mkurbanparMod Feb, 2012) -! -! -! !LOCAL VARIABLES: -!EOP - integer :: ier ! error status - real(r8), allocatable :: mask_r8(:) ! float of tdomain%mask - real(r8) :: sum_fldi ! global sum of dummy input fld - real(r8) :: sum_fldo ! global sum of dummy output fld - integer :: ni,no ! indices - real(r8) :: relerr = 0.00001_r8 ! max error: sum overlap wts ne 1 - character(len=*), parameter :: subname = 'mkurban_pct' -!----------------------------------------------------------------------- - - ! Error checks for array size consistencies - - if (size(urbn_i) /= tdomain%ns .or. & - size(urbn_o) /= ldomain%ns) then - write(6,*) subname//' ERROR: array size inconsistencies' - write(6,*) 'size(urbn_i) = ', size(urbn_i) - write(6,*) 'tdomain%ns = ', tdomain%ns - write(6,*) 'size(urbn_o) = ', size(urbn_o) - write(6,*) 'ldomain%ns = ', ldomain%ns - call abort() - end if - if (size(frac_dst) /= ldomain%ns) then - write(6,*) subname//' ERROR: array size inconsistencies' - write(6,*) 'size(frac_dst) = ', size(frac_dst) - write(6,*) 'ldomain%ns = ', ldomain%ns - call abort() - end if - - ! Error checks for domain and map consistencies - - call domain_checksame( tdomain, ldomain, tgridmap ) - - ! Determine urbn_o on ouput grid: - ! Area-average percent cover on input grid to output grid - ! and correct according to land landmask - ! Note that percent cover is in terms of total grid area. - - call gridmap_areaave_srcmask(tgridmap, urbn_i, urbn_o, nodata=0._r8, mask_src=tdomain%mask, frac_dst=frac_dst) - - ! Check for conservation - - do no = 1, ldomain%ns - if ((urbn_o(no)) > 100.000001_r8) then - write (6,*) 'MKURBAN error: urban = ',urbn_o(no), & - ' greater than 100.000001 for column, row = ',no - call abort() - end if - enddo - - ! Global sum of output field -- must multiply by fraction of - ! output grid that is land as determined by input grid - - allocate(mask_r8(tdomain%ns), stat=ier) - if (ier/=0) call abort() - mask_r8 = tdomain%mask - call gridmap_check( tgridmap, mask_r8, frac_dst, subname ) - - ! (Error check2 in mkurban_pct_diagnostics, which should be called separately) - - deallocate (mask_r8) - -end subroutine mkurban_pct -!----------------------------------------------------------------------- - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: mkurban_pct_diagnostics -! -! !INTERFACE: -subroutine mkurban_pct_diagnostics(ldomain, tdomain, tgridmap, urbn_i, urbn_o, ndiag, dens_class, frac_dst) -! -! !DESCRIPTION: -! print diagnostics related to pct urban -! -! This is intended to be called after mkurban_pct, but is split out into a separate -! routine so that modifications to urbn_o can be made in between the two calls (e.g., -! setting urbn_o to 0 wherever it is less than a certain threshold; the rules for doing -! this can't always be applied inline in mkurban_pct). -! -! !USES: - use mkdomainMod , only : domain_type - use mkgridmapMod, only : gridmap_type - use mkvarpar -! -! !ARGUMENTS: - implicit none - type(domain_type) , intent(in) :: ldomain - type(domain_type) , intent(in) :: tdomain ! local domain - type(gridmap_type), intent(in) :: tgridmap ! local gridmap - real(r8) , intent(in) :: urbn_i(:) ! input grid: percent urban - real(r8) , intent(in) :: urbn_o(:) ! output grid: percent urban - real(r8) , intent(in) :: frac_dst(:) ! output fractions - integer , intent(in) :: ndiag ! unit number for diag out - - integer , intent(in), optional :: dens_class ! density class -! -! !REVISION HISTORY: -! Author: Bill Sacks -! (Moved from mkurbanparMod Feb, 2012) -! -! -! !LOCAL VARIABLES: -!EOP - real(r8) :: gurbn_i ! input grid: global urbn - real(r8) :: garea_i ! input grid: global area - real(r8) :: gurbn_o ! output grid: global urbn - real(r8) :: garea_o ! output grid: global area - integer :: ni,no,k ! indices - character(len=*), parameter :: subname = 'mkurban_pct_diagnostics' -!----------------------------------------------------------------------- - - ! Error check inputs - if (size(frac_dst) /= ldomain%ns) then - write(6,*) subname//' ERROR: array size inconsistencies' - write(6,*) 'size(frac_dst) = ', size(frac_dst) - write(6,*) 'ldomain%ns = ', ldomain%ns - call abort() - end if - - ! ----------------------------------------------------------------- - ! Error check2 - ! Compare global areas on input and output grids - ! ----------------------------------------------------------------- - - ! Input grid - - gurbn_i = 0._r8 - garea_i = 0._r8 - - do ni = 1, tdomain%ns - garea_i = garea_i + tgridmap%area_src(ni)*re**2 - gurbn_i = gurbn_i + urbn_i(ni)*(tgridmap%area_src(ni)/100._r8)*& - tdomain%mask(ni)*re**2 - end do - - ! Output grid - - gurbn_o = 0._r8 - garea_o = 0._r8 - - do no = 1, ldomain%ns - garea_o = garea_o + tgridmap%area_dst(no)*re**2 - gurbn_o = gurbn_o + urbn_o(no)* (tgridmap%area_dst(no)/100._r8)*& - frac_dst(no)*re**2 - end do - - ! Diagnostic output - - write (ndiag,*) - write (ndiag,'(1x,70a1)') ('=',k=1,70) - if (present(dens_class)) then - write (ndiag,'(1x,a,i0)') 'Urban Output -- class ', dens_class - else - write (ndiag,'(1x,a)') 'Urban Output' - end if - write (ndiag,'(1x,70a1)') ('=',k=1,70) - - write (ndiag,*) - write (ndiag,'(1x,70a1)') ('.',k=1,70) - write (ndiag,2001) -2001 format (1x,'surface type input grid area output grid area'/ & - 1x,' 10**6 km**2 10**6 km**2 ') - write (ndiag,'(1x,70a1)') ('.',k=1,70) - write (ndiag,*) - write (ndiag,2003) gurbn_i*1.e-06,gurbn_o*1.e-06 - write (ndiag,2004) garea_i*1.e-06,garea_o*1.e-06 -2002 format (1x,'urban ',f14.3,f17.3) -2003 format (1x,'urban ',f14.3,f22.8) -2004 format (1x,'all surface ',f14.3,f17.3) - -end subroutine mkurban_pct_diagnostics -!----------------------------------------------------------------------- - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: mkelev -! -! !INTERFACE: -subroutine mkelev(ldomain, mapfname, datfname, varname, ndiag, elev_o) -! -! !DESCRIPTION: -! Make elevation data -! -! !USES: - use mkdomainMod , only : domain_type, domain_clean, domain_read, domain_checksame - use mkgridmapMod - use mkvarpar - use mkvarctl - use mkncdio - use mkdiagnosticsMod, only : output_diagnostics_continuous -! -! !ARGUMENTS: - implicit none - type(domain_type), intent(in) :: ldomain - character(len=*) , intent(in) :: mapfname ! input mapping file name - character(len=*) , intent(in) :: datfname ! input data file name - integer , intent(in) :: ndiag ! unit number for diag out - character(len=*) , intent(in) :: varname ! topo variable name - real(r8) , intent(out):: elev_o(:) ! output elevation data -! -! -! !CALLED FROM: -! subroutine mksrfdat in module mksrfdatMod -! -! !REVISION HISTORY: -! Author: Keith Oleson -! -! -! !LOCAL VARIABLES: -!EOP - type(domain_type) :: tdomain ! local domain - type(gridmap_type) :: tgridmap ! local gridmap - - real(r8), allocatable :: elev_i(:) ! canyon_height to width ratio in - real(r8), allocatable :: frac_dst(:) ! output fractions - integer :: ns_i,ns_o ! indices - integer :: k,l,n,m,ni ! indices - integer :: ncidi,dimid,varid ! input netCDF id's - integer :: ier ! error status - character(len=256) :: name ! name of attribute - character(len=256) :: unit ! units of attribute - character(len= 32) :: subname = 'mkelev' -!----------------------------------------------------------------------- - - write (6,*) 'Attempting to make elevation .....' - call shr_sys_flush(6) - - ns_o = ldomain%ns - - ! ----------------------------------------------------------------- - ! Read input file - ! ----------------------------------------------------------------- - - ! Obtain input grid info, read local fields - - call domain_read(tdomain,datfname) - - ns_i = tdomain%ns - allocate(elev_i(ns_i), stat=ier) - allocate(frac_dst(ns_o), stat=ier) - if (ier /= 0) then - write(6,*)'mkelev allocation error'; call abort() - end if - - write (6,*) 'Open elevation file: ', trim(datfname) - call check_ret(nf_open(datfname, 0, ncidi), subname) - call check_ret(nf_inq_varid (ncidi, trim(varname), varid), subname) - call check_ret(nf_get_var_double (ncidi, varid, elev_i), subname) - call check_ret(nf_close(ncidi), subname) - - ! Read topo elev dataset with unit mask everywhere - - call gridmap_mapread(tgridmap, mapfname) - - ! Error checks for domain and map consistencies - ! Note that the topo dataset has no landmask - so a unit landmask is assumed - - call domain_checksame( tdomain, ldomain, tgridmap ) - - ! Obtain frac_dst - call gridmap_calc_frac_dst(tgridmap, tdomain%mask, frac_dst) - - ! Determine elev_o on output grid - - elev_o(:) = 0. - - call gridmap_areaave_srcmask(tgridmap, elev_i, elev_o, nodata=0._r8, mask_src=tdomain%mask, frac_dst=frac_dst) - - call output_diagnostics_continuous(elev_i, elev_o, tgridmap, "Urban elev variable", "m", ndiag, tdomain%mask, frac_dst) - - - ! Deallocate dynamic memory - - call domain_clean(tdomain) - call gridmap_clean(tgridmap) - deallocate (elev_i) - deallocate (frac_dst) - - write (6,*) 'Successfully made elevation' - write (6,*) - call shr_sys_flush(6) - -end subroutine mkelev - -!----------------------------------------------------------------------- - -end module mkurbanparCommonMod diff --git a/tools/mksurfdata_map/src/mkurbanparMod.F90 b/tools/mksurfdata_map/src/mkurbanparMod.F90 deleted file mode 100644 index 49ce95dd07..0000000000 --- a/tools/mksurfdata_map/src/mkurbanparMod.F90 +++ /dev/null @@ -1,759 +0,0 @@ -module mkurbanparMod -!----------------------------------------------------------------------- -!BOP -! -! !MODULE: mkurbanpar -! -! !DESCRIPTION: -! Make Urban Parameter data -! -! !REVISION HISTORY: -! Author: Bill Sacks -! -!----------------------------------------------------------------------- -! !USES: - use shr_kind_mod, only : r8 => shr_kind_r8 - use shr_sys_mod , only : shr_sys_flush - use mkvarctl, only : ispval - implicit none - - private - -! !PUBLIC MEMBER FUNCTIONS: - public :: mkurbanInit - public :: mkurban - public :: mkurbanpar - - ! The following could be private, but because there are associated test routines in a - ! separate module, it needs to be public - public :: normalize_urbn_by_tot - -! !PUBLIC DATA MEMBERS: - integer :: numurbl ! number of urban classes - integer :: nlevurb = ispval ! number of urban layers - - public :: numurbl - public :: nlevurb - -! !PRIVATE DATA MEMBERS: - ! flag to indicate nodata for index variables in output file: - integer, parameter :: index_nodata = 0 - character(len=*), parameter :: modname = 'mkurbanparMod' - - private :: index_nodata - private :: modname - -!EOP - -contains - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: mkurbanInit -! -! !INTERFACE: -subroutine mkurbanInit(datfname) -! -! !DESCRIPTION: -! Initialize variables needed for urban -! -! !USES: - use mkncdio -! -! !ARGUMENTS: - implicit none - character(len=*), intent(in) :: datfname ! input data file name (same as file used in mkurban) -! -! !CALLED FROM: -! subroutine mksrfdat in module mksrfdatMod -! -! !REVISION HISTORY: -! Author: Bill Sacks -! -! -! !LOCAL VARIABLES: - integer :: ncid,dimid ! input netCDF id's - - character(len=*), parameter :: subname = 'mkurbanInit' -!EOP -!----------------------------------------------------------------------- - - ! Set numurbl - call check_ret(nf_open(datfname, 0, ncid), subname) - call check_ret(nf_inq_dimid (ncid, 'density_class', dimid), subname) - call check_ret(nf_inq_dimlen (ncid, dimid, numurbl), subname) - call check_ret(nf_inq_dimid (ncid, 'nlevurb', dimid), subname) - call check_ret(nf_inq_dimlen (ncid, dimid, nlevurb), subname) - call check_ret(nf_close(ncid), subname) - -end subroutine mkurbanInit -!----------------------------------------------------------------------- - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: mkurban -! -! !INTERFACE: -subroutine mkurban(ldomain, mapfname, datfname, ndiag, zero_out, & - urbn_o, urbn_classes_o, region_o) -! -! !DESCRIPTION: -! make total percent urban, breakdown into urban classes, and region ID on the output grid -! -! urbn_classes_o(n, i) gives the percent of the urban area in grid cell n that is in class #i. -! This is normalized so that sum(urbn_classes_o(n,:)) = 100 for all n, even for grid -! cells where urbn_o(n) = 0 (in the case where urbn_o(n) = 0, we come up with an -! arbitrary assignment of urban into the different classes). -! -! See comments under the normalize_urbn_by_tot subroutine for how urbn_classes_o is -! determined when the total % urban is 0, according to the input data. Note that this -! also applies when all_urban=.true., for points that have 0 urban according to the input -! data. -! -! TODO (WJS 6-12-14): I think this could be rewritten slightly to take advantage of the -! new mkpctPftTypeMod (which should then be renamed to something more general; or maybe -! better, in terms of maintaining helpful abstractions, there could be a new type to -! handle urban, and both that and pct_pft_type could be build on a single set of shared -! code - either as a single base class or through a "has-a" mechanism). This would allow -! us to combine urbn_o and urbn_classes_o into a single derived type variable. I think -! this would also replace the use of normalize_classes_by_gcell, and maybe some other -! urban-specific code. -! -! !USES: - use mkdomainMod , only : domain_type, domain_clean, domain_read - use mkgridmapMod - use mkindexmapMod, only : get_dominant_indices - use mkurbanparCommonMod, only : mkurban_pct, mkurban_pct_diagnostics, MIN_DENS - use mkutilsMod , only : normalize_classes_by_gcell - use mkvarctl , only : all_urban - use mkvarpar - use mkncdio - use mkdiagnosticsMod, only : output_diagnostics_index -! -! !ARGUMENTS: - implicit none - type(domain_type), intent(in) :: ldomain - character(len=*) , intent(in) :: mapfname ! input mapping file name - character(len=*) , intent(in) :: datfname ! input data file name - integer , intent(in) :: ndiag ! unit number for diag out - logical , intent(in) :: zero_out ! if should zero urban out - real(r8) , intent(out):: urbn_o(:) ! output grid: total % urban - real(r8) , intent(out):: urbn_classes_o(:,:) ! output grid: breakdown of total urban into each class - ! (dimensions: (ldomain%ns, numurbl)) - integer , intent(out):: region_o(:) ! output grid: region ID -! -! !CALLED FROM: -! subroutine mksrfdat in module mksrfdatMod -! -! !REVISION HISTORY: -! Author: Bill Sacks -! -! -! !LOCAL VARIABLES: -!EOP - type(domain_type) :: tdomain ! local domain - type(gridmap_type) :: tgridmap ! local gridmap - real(r8), allocatable :: urbn_classes_gcell_i(:,:) ! input grid: percent urban in each density class - ! (% of total grid cell area) - real(r8), allocatable :: urbn_classes_gcell_o(:,:) ! output grid: percent urban in each density class - real(r8), allocatable :: frac_dst(:) ! output fractions - ! (% of total grid cell area) - integer , allocatable :: region_i(:) ! input grid: region ID - integer :: ni,no,ns,k ! indices - integer :: ncid,dimid,varid ! input netCDF id's - integer :: dimlen ! netCDF dimension length - integer :: max_region ! maximum region index - integer :: ier ! error status - - character(len=*), parameter :: subname = 'mkurban' -!----------------------------------------------------------------------- - - write (6,*) 'Attempting to make %urban .....' - - ! Obtain input grid info, read local fields - - call gridmap_mapread(tgridmap, mapfname) - call domain_read(tdomain, datfname) - - ns = tdomain%ns - - allocate(urbn_classes_gcell_i(ns, numurbl), & - urbn_classes_gcell_o(ldomain%ns, numurbl), & - frac_dst(ldomain%ns), & - stat=ier) - if (ier/=0) call abort() - - ! Obtain frac_dst - call gridmap_calc_frac_dst(tgridmap, tdomain%mask, frac_dst) - - write (6,*) 'Open urban file: ', trim(datfname) - call check_ret(nf_open(datfname, 0, ncid), subname) - call check_ret(nf_inq_varid (ncid, 'PCT_URBAN', varid), subname) - call check_ret(nf_get_var_double (ncid, varid, urbn_classes_gcell_i), subname) - - ! Determine % urban by density class on the output grid - do k = 1, numurbl - call mkurban_pct(ldomain, tdomain, tgridmap, urbn_classes_gcell_i(:,k), urbn_classes_gcell_o(:,k), frac_dst) - end do - - ! Determine total % urban - do no = 1, ldomain%ns - urbn_o(no) = sum(urbn_classes_gcell_o(no,:)) - end do - - call normalize_urbn_by_tot(urbn_classes_gcell_o, urbn_o, urbn_classes_o) - - ! Handle special cases - - ! Note that, for all these adjustments of total urban %, we do not change anything - ! about the breakdown into the different urban classes. In particular: when urbn_o is - ! set to 0 for a point, the breakdown into the different urban classes is maintained - ! as it was before. - if (all_urban) then - urbn_o(:) = 100._r8 - else if (zero_out) then - urbn_o(:) = 0._r8 - else - ! Set points to 0% if they fall below a given threshold - do no = 1, ldomain%ns - if (urbn_o(no) < MIN_DENS) then - urbn_o(no) = 0._r8 - end if - end do - end if - - ! Print diagnostics - ! First, recompute urbn_classes_gcell_o, based on any changes we have made to urbn_o - ! while handling special cases - call normalize_classes_by_gcell(urbn_classes_o, urbn_o, urbn_classes_gcell_o) - do k = 1, numurbl - call mkurban_pct_diagnostics(ldomain, tdomain, tgridmap, & - urbn_classes_gcell_i(:,k), urbn_classes_gcell_o(:,k), & - ndiag, dens_class=k, frac_dst=frac_dst) - end do - - write (6,*) 'Successfully made %urban' - - - write(6,*) 'Attempting to make urban region .....' - - ! Read in region field - ! Note: we do this here, rather than with the rest of the reads above, because we - ! expect the input urban fields to be large, so we're just reading the fields as - ! they're needed to try to avoid unnecessary memory paging - - allocate(region_i(ns), stat=ier) - if (ier/=0) call abort() - call check_ret(nf_inq_varid (ncid, 'REGION_ID', varid), subname) - call check_ret(nf_get_var_int (ncid, varid, region_i), subname) - - ! Determine max region value, and make sure it doesn't exceed bounds of the lookup tables. - ! - ! (Note: this check assumes that region_i=1 refers to region(1), region_i=2 refers to - ! region(2), etc. The alternative would be to use a coordinate variable associated with - ! the region dimension of the lookup table, which could result in an arbitrary mapping - ! between region values and the indices of the lookup table; however, this use of - ! coordinate variables currently isn't supported by lookup_2d_netcdf [as of 2-8-12].) - - max_region = maxval(region_i) - call check_ret(nf_inq_dimid (ncid, 'region', dimid), subname) - call check_ret(nf_inq_dimlen (ncid, dimid, dimlen), subname) - if (max_region > dimlen) then - write(6,*) modname//':'//subname// & - ' ERROR: max region value exceeds length of region dimension' - write(6,*) 'max region value : ', max_region - write(6,*) 'length of region dimension: ', dimlen - call abort() - end if - - ! Determine dominant region for each output cell - - call get_dominant_indices(tgridmap, region_i, region_o, 1, max_region, index_nodata, mask_src=tdomain%mask) - - write (6,*) 'Successfully made urban region' - write (6,*) - - ! Output diagnostics - - call output_diagnostics_index(region_i, region_o, tgridmap, 'Urban Region ID', & - 1, max_region, ndiag, mask_src=tdomain%mask, frac_dst=frac_dst) - - ! Deallocate dynamic memory & other clean up - - call check_ret(nf_close(ncid), subname) - call domain_clean(tdomain) - call gridmap_clean(tgridmap) - deallocate (urbn_classes_gcell_i, urbn_classes_gcell_o, region_i, frac_dst) - -end subroutine mkurban -!----------------------------------------------------------------------- - -!------------------------------------------------------------------------------ -!BOP -! -! !IROUTINE: normalize_urbn_by_tot -! -! !INTERFACE: -subroutine normalize_urbn_by_tot(classes_pct_gcell, sums, classes_pct_tot) -! -! !DESCRIPTION: -! Normalizes urban class areas to produce % cover of each class, as % of total urban area -! -! Specifically: Given (1) an array specifying the % cover of each urban class, as a % of -! the total grid cell area ('classes_pct_gcell'), and (2) a vector giving the total urban -! area in each grid cell, expressed as % of the grid cell area: Returns an array -! ('classes_pct_tot') of the same dimensionality as classes_pct_gcell, where the values -! now give % cover of each class as a % of the total urban area. -! -! Assumes that sums(n) = sum(classes_pct_gcell(n,:)) -! -! When sums(n) = 0, the creation of classes_pct_tot(n,:) is ambiguous. Here we use the -! rule that all area is assigned to the medium-density class, defined by parameter MD. -! -! The returned array satisfies sum(classes_pct_tot(n,:))==100 for all n (within rounding error) -! -! !USES: -! -! !ARGUMENTS: - implicit none - real(r8), intent(in) :: classes_pct_gcell(:,:) ! % cover of classes as % of grid cell - real(r8), intent(in) :: sums(:) ! totals, as % of grid cell - real(r8), intent(out):: classes_pct_tot(:,:) ! % cover of classes as % of total -! -! !REVISION HISTORY: -! Author: Bill Sacks -! -! -! !LOCAL VARIABLES: -!EOP - integer :: n ! index - integer :: n_max ! number of points - integer :: nclasses ! number of classes - real(r8) :: suma ! sum for error check - - ! index of medium-density class, which is where we assign urban areas when the total - ! urban area is 0 - integer, parameter :: MD = 3 - - ! relative error tolerance for error check - real(r8), parameter :: relerr = 1.e-10_r8 - - character(len=*), parameter :: subname = 'normalize_urbn_by_tot' -!----------------------------------------------------------------------- - - ! Error-check inputs - - n_max = size(sums) - if (size(classes_pct_tot, 1) /= n_max .or. & - size(classes_pct_gcell, 1) /= n_max) then - write(6,*) subname//' ERROR: array size mismatch' - write(6,*) 'size(sums) = ', n_max - write(6,*) 'size(classes_pct_tot, 1) = ', size(classes_pct_tot, 1) - write(6,*) 'size(classes_pct_gcell, 1) = ', size(classes_pct_gcell, 1) - call abort() - end if - - if (size(classes_pct_tot, 2) /= size(classes_pct_gcell, 2)) then - write(6,*) subname//' ERROR: array size mismatch' - write(6,*) 'size(classes_pct_tot, 2) = ', size(classes_pct_tot, 2) - write(6,*) 'size(classes_pct_gcell, 2) = ', size(classes_pct_gcell, 2) - call abort() - end if - - nclasses = size(classes_pct_gcell, 2) - if (MD > nclasses) then - write(6,*) subname//' ERROR: MD exceeds nclasses' - write(6,*) 'MD = ', MD - write(6,*) 'nclasses = ', nclasses - call abort() - end if - - ! Do the work - - do n = 1, n_max - if (sums(n) > 0._r8) then - classes_pct_tot(n,:) = classes_pct_gcell(n,:)/sums(n) * 100._r8 - else - ! Creation of classes_pct_tot is ambiguous. Apply the rule that all area is - ! assigned to the medium-density class. - classes_pct_tot(n,:) = 0._r8 - classes_pct_tot(n,MD) = 100._r8 - end if - end do - - ! Error-check output: Make sure sum(classes_pct_tot(n,:)) = 100 for all n - - do n = 1, n_max - suma = sum(classes_pct_tot(n,:)) - if (abs(suma/100._r8 - 1._r8) > relerr) then - write(6,*) subname//' ERROR: sum does not equal 100 at point ', n - write(6,*) 'suma = ', suma - call abort() - end if - end do - -end subroutine normalize_urbn_by_tot -!----------------------------------------------------------------------- - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: mkurbanpar -! -! !INTERFACE: -subroutine mkurbanpar(datfname, ncido, region_o, urbn_classes_gcell_o, urban_skip_abort_on_invalid_data_check) -! -! !DESCRIPTION: -! Make Urban Parameter data -! -! Note that, in a grid cell with region_o==r, parameter values are filled from region r -! for ALL density classes. Thus, the parameter variables have a numurbl dimension along -! with their other dimensions. -! -! Note that we will have a 'nodata' value (given by the fill_val value associated with -! each parameter) wherever (1) we have a nodata value for region_o, or (2) the parameter -! has nodata for the given region/density combination in the input lookup table. -! -! !USES: - use mkdomainMod , only : domain_type, domain_clean, domain_read - use mkindexmapMod, only : dim_slice_type, lookup_2d_netcdf - use mkvarpar - use mkncdio -! -! !ARGUMENTS: - implicit none - character(len=*) , intent(in) :: datfname ! input data file name - integer , intent(in) :: ncido ! output netcdf file id - integer , intent(in) :: region_o(:) ! output grid: region ID (length: ns_o) - real(r8) , intent(in) :: urbn_classes_gcell_o(:,:) ! output grid: percent urban in each density class - ! (% of total grid cell area) (dimensions: ns_o, numurbl) - logical , intent(in) :: urban_skip_abort_on_invalid_data_check - -! !CALLED FROM: -! subroutine mksrfdat in module mksrfdatMod -! -! !REVISION HISTORY: -! Author: Bill Sacks -! -! -! !LOCAL VARIABLES: -!EOP - ! Type to store information about each urban parameter - type param - character(len=32) :: name ! name in input & output files - real(r8) :: fill_val ! value to put where we have no data in output - logical :: check_invalid ! should we check whether there are any invalid data in the output? - end type param - - real(r8), allocatable :: data_scalar_o(:,:) ! output array for parameters with no extra dimensions - real(r8), allocatable :: data_rad_o(:,:,:,:) ! output array for parameters dimensioned by numrad & numsolar - real(r8), allocatable :: data_levurb_o(:,:,:) ! output array for parameters dimensioned by nlevurb - integer , allocatable :: unity_dens_o(:,:) ! artificial density indices - integer :: nlevurb_i ! input grid: number of urban vertical levels - integer :: numsolar_i ! input grid: number of solar type (DIR/DIF) - integer :: numrad_i ! input grid: number of solar bands (VIS/NIR) - integer :: m,n,no,ns_o,p,k ! indices - integer :: ncidi,dimid,varid ! netCDF id's - integer :: ier ! error status - character(len=nf_max_name) :: varname ! variable name - - ! information on extra dimensions for lookup tables greater than 2-d: - type(dim_slice_type), allocatable :: extra_dims(:) - - ! suffix for variables dimensioned by numsolar, for each value of numsolar: - character(len=8), parameter :: solar_suffix(numsolar) = (/'_DIR', '_DIF'/) - - ! value to put where we have no data in output variables, for real-valued parameters - real(r8), parameter :: fill_val_real = 0._r8 - - ! To add a new urban parameter, simply add an element to one of the below lists - ! (params_scalar, params_rad or params_levurb) - - ! Urban parameters with no extra dimensions - type(param), parameter :: params_scalar(13) = & - (/ param('CANYON_HWR', fill_val_real, .true.), & - param('EM_IMPROAD', fill_val_real, .true.), & - param('EM_PERROAD', fill_val_real, .true.), & - param('EM_ROOF', fill_val_real, .true.), & - param('EM_WALL', fill_val_real, .true.), & - param('HT_ROOF', fill_val_real, .true.), & - param('THICK_ROOF', fill_val_real, .true.), & - param('THICK_WALL', fill_val_real, .true.), & - param('T_BUILDING_MIN', fill_val_real, .true.), & - param('WIND_HGT_CANYON', fill_val_real, .true.), & - param('WTLUNIT_ROOF', fill_val_real, .true.), & - param('WTROAD_PERV', fill_val_real, .true.), & - - ! Note that NLEV_IMPROAD is written as an integer, meaning that type conversion occurs - ! by truncation. Thus we expect the values in the NLEV_IMPROAD lookup table to be exact; - ! e.g., if a value were 1.99999 rather than 2.0000, it would be written as 1 instead of 2 - ! Also note: we use fill_val=-1 rather than 0, because 0 appears in the lookup table - param('NLEV_IMPROAD', -1, .true.) /) - - ! Urban parameters dimensioned by numrad & numsolar - type(param), parameter :: params_rad(4) = & - (/ param('ALB_IMPROAD', fill_val_real, .true.), & - param('ALB_PERROAD', fill_val_real, .true.), & - param('ALB_ROOF', fill_val_real, .true.), & - param('ALB_WALL', fill_val_real, .true.) /) - - ! Urban parameters dimensioned by nlevurb - type(param), parameter :: params_levurb(6) = & - (/ param('TK_ROOF', fill_val_real, .true.), & - param('TK_WALL', fill_val_real, .true.), & - param('CV_ROOF', fill_val_real, .true.), & - param('CV_WALL', fill_val_real, .true.), & - - ! Impervious road thermal conductivity and heat capacity have varying levels of - ! data. Thus, we expect to find some missing values in the lookup table -- we - ! do not want to treat that as an error -- thus, we set check_invalid=.false. - param('CV_IMPROAD', fill_val_real, .false.), & - param('TK_IMPROAD', fill_val_real, .false.) /) - - - character(len=*), parameter :: subname = 'mkurbanpar' -!----------------------------------------------------------------------- - - write (6,*) 'Attempting to make Urban Parameters .....' - call shr_sys_flush(6) - - ! Determine & error-check array sizes - ns_o = size(region_o) - if (size(urbn_classes_gcell_o, 1) /= ns_o) then - write(6,*) modname//':'//subname//' ERROR: array size mismatch' - write(6,*) 'size(region_o) = ', size(region_o) - write(6,*) 'size(urbn_classes_gcell_o, 1) = ', size(urbn_classes_gcell_o, 1) - call abort() - end if - if (size(urbn_classes_gcell_o, 2) /= numurbl) then - write(6,*) modname//':'//subname//' ERROR: array size mismatch' - write(6,*) 'size(urbn_classes_gcell_o, 2) = ', size(urbn_classes_gcell_o, 2) - write(6,*) 'numurbl = ', numurbl - end if - - - ! Read dimensions from input file - - write (6,*) 'Open urban parameter file: ', trim(datfname) - call check_ret(nf_open(datfname, 0, ncidi), subname) - call check_ret(nf_inq_dimid(ncidi, 'nlevurb', dimid), subname) - call check_ret(nf_inq_dimlen(ncidi, dimid, nlevurb_i), subname) - call check_ret(nf_inq_dimid(ncidi, 'numsolar', dimid), subname) - call check_ret(nf_inq_dimlen(ncidi, dimid, numsolar_i), subname) - call check_ret(nf_inq_dimid(ncidi, 'numrad', dimid), subname) - call check_ret(nf_inq_dimlen(ncidi, dimid, numrad_i), subname) - - if (nlevurb_i /= nlevurb) then - write(6,*)'MKURBANPAR: parameter nlevurb= ',nlevurb, & - 'does not equal input dataset nlevurb= ',nlevurb_i - call abort() - endif - if (numsolar_i /= numsolar) then - write(6,*)'MKURBANPAR: parameter numsolar= ',numsolar, & - 'does not equal input dataset numsolar= ',numsolar_i - call abort() - endif - if (numrad_i /= numrad) then - write(6,*)'MKURBANPAR: parameter numrad= ',numrad, & - 'does not equal input dataset numrad= ',numrad_i - call abort() - endif - - ! Create an array that will hold the density indices - ! In a given grid cell, we output parameter values for all density classes, for the - ! region of that grid cell. In order to do this while still using the lookup_2d - ! routine, we create a dummy unity_dens_o array that contains the density values - ! passed to the lookup routine. - - allocate(unity_dens_o(ns_o, numurbl)) - do k = 1, numurbl - unity_dens_o(:,k) = k - end do - - ! Handle urban parameters with no extra dimensions - - allocate(data_scalar_o(ns_o, numurbl), stat=ier) - if (ier /= 0) then - write(6,*)'mkurbanpar allocation error'; call abort() - end if - - do p = 1, size(params_scalar) - call lookup_and_check_err(params_scalar(p)%name, params_scalar(p)%fill_val, & - params_scalar(p)%check_invalid, urban_skip_abort_on_invalid_data_check, & - data_scalar_o, 0) - - call check_ret(nf_inq_varid(ncido, params_scalar(p)%name, varid), subname) - ! In the following, note that type conversion occurs if we're writing to a variable of type - ! other than double; e.g., for an integer, conversion occurs by truncation! - call check_ret(nf_put_var_double(ncido, varid, data_scalar_o), subname) - end do - - deallocate(data_scalar_o) - - ! Handle urban parameters dimensioned by numrad & numsolar - - allocate(data_rad_o(ns_o, numurbl, numrad, numsolar), stat=ier) - if (ier /= 0) then - write(6,*)'mkurbanpar allocation error'; call abort() - end if - - allocate(extra_dims(2)) - extra_dims(1)%name = 'numrad' - extra_dims(2)%name = 'numsolar' - - do p = 1, size(params_rad) - do m = 1,numsolar - extra_dims(2)%val = m - do n = 1,numrad - extra_dims(1)%val = n - - call lookup_and_check_err(params_rad(p)%name, params_rad(p)%fill_val, & - params_rad(p)%check_invalid, urban_skip_abort_on_invalid_data_check, & - data_rad_o(:,:,n,m), & - 2, extra_dims) - end do - end do - - ! Special handling of numsolar: rather than outputting variables with a numsolar - ! dimension, we output separate variables for each value of numsolar - do m = 1,numsolar - if (len_trim(params_rad(p)%name) + len_trim(solar_suffix(m)) > len(varname)) then - write(6,*) 'variable name exceeds length of varname' - write(6,*) trim(params_rad(p)%name)//trim(solar_suffix(m)) - call abort() - end if - varname = trim(params_rad(p)%name)//trim(solar_suffix(m)) - call check_ret(nf_inq_varid(ncido, varname, varid), subname) - ! In the following, note that type conversion occurs if we're writing to a variable of type - ! other than double; e.g., for an integer, conversion occurs by truncation! - call check_ret(nf_put_var_double(ncido, varid, data_rad_o(:,:,:,m)), subname) - end do - end do - - deallocate(data_rad_o) - deallocate(extra_dims) - - ! Handle urban parameters dimensioned by nlevurb - - allocate(data_levurb_o(ns_o, numurbl, nlevurb), stat=ier) - if (ier /= 0) then - write(6,*)'mkurbanpar allocation error'; call abort() - end if - - allocate(extra_dims(1)) - extra_dims(1)%name = 'nlevurb' - - do p = 1, size(params_levurb) - do n = 1,nlevurb - extra_dims(1)%val = n - - call lookup_and_check_err(params_levurb(p)%name, params_levurb(p)%fill_val, & - params_levurb(p)%check_invalid, & - urban_skip_abort_on_invalid_data_check, data_levurb_o(:,:,n), & - 1, extra_dims) - end do - - call check_ret(nf_inq_varid(ncido, params_levurb(p)%name, varid), subname) - ! In the following, note that type conversion occurs if we're writing to a variable of type - ! other than double; e.g., for an integer, conversion occurs by truncation! - call check_ret(nf_put_var_double(ncido, varid, data_levurb_o), subname) - end do - - deallocate(data_levurb_o) - deallocate(extra_dims) - - - call check_ret(nf_close(ncidi), subname) - call check_ret(nf_sync(ncido), subname) - - write (6,*) 'Successfully made Urban Parameters' - write (6,*) - call shr_sys_flush(6) - - deallocate(unity_dens_o) - -contains -!------------------------------------------------------------------------------ - subroutine lookup_and_check_err(varname, fill_val, check_invalid, & - urban_skip_abort_on_invalid_data_check, data, n_extra_dims, extra_dims) - - ! Wrapper to lookup_2d_netcdf: Loops over each density class, calling lookup_2d_netcdf - ! with that density class and filling the appropriate slice of the data array. Also - ! checks for any errors, aborting if there were any. - ! - ! Note that the lookup_2d_netcdf routine is designed to work with a single value of - ! each of the indices. However, we want to fill parameter values for ALL density - ! classes. This is why we loop over density class in this routine. - ! - ! Note: inherits a number of variables from the parent routine - - use mkindexmapMod, only : lookup_2d_netcdf - - implicit none - character(len=*), intent(in) :: varname ! name of lookup table - real(r8) , intent(in) :: fill_val ! value to put where we have no data in output variables - logical , intent(in) :: check_invalid ! should we check whether there are any invalid data in the output? - logical , intent(in) :: urban_skip_abort_on_invalid_data_check - - real(r8) , intent(out):: data(:,:) ! output from lookup_2d_netcdf - integer , intent(in) :: n_extra_dims ! number of extra dimensions in the lookup table - - ! slice to use if lookup table variable has more than 2 dimensions: - type(dim_slice_type), intent(in), optional :: extra_dims(:) - - ! Local variables: - - integer :: k,n ! indices - integer :: ierr ! error return code - - - do k = 1, numurbl - ! In the following, note that unity_dens_o(:,k) has been constructed so that - ! unity_dens_o(:,k)==k everywhere. Thus, we fill data(:,k) with the parameter - ! values corresponding to density class k. - ! Also note: We use invalid_okay=.true. because we fill all density classes, - ! some of which may have invalid entries. Because doing so disables some error - ! checking, we do our own error checking after the call. - call lookup_2d_netcdf(ncidi, varname, .true., & - 'density_class', 'region', n_extra_dims, & - unity_dens_o(:,k), region_o, fill_val, data(:,k), ierr, & - extra_dims=extra_dims, nodata=index_nodata, & - invalid_okay=.true.) - - if (ierr /= 0) then - write(6,*) modname//':'//subname//' ERROR in lookup_2d_netcdf for ', & - trim(varname), ' class', k, ': err=', ierr - call abort() - end if - - if (check_invalid) then - ! Make sure we have valid parameter values wherever we have non-zero urban cover - do n = 1, ns_o - ! This check assumes that fill_val doesn't appear in any of the valid entries - ! of the lookup table - if (urbn_classes_gcell_o(n,k) > 0. .and. data(n,k) == fill_val) then - write(6,*) modname//':'//subname//' ERROR: fill value found in output where urban cover > 0' - write(6,*) 'var: ', trim(varname) - write(6,*) 'class: ', k - write(6,*) 'n: ', n - write(6,*) 'region: ', region_o(n) - write(6,*) 'urbn_classes_gcell_o(n,k): ', urbn_classes_gcell_o(n,k) - if (.not. urban_skip_abort_on_invalid_data_check) then - ! NOTE(bja, 2015-01) added to work around a ?bug? noted in - ! /glade/p/cesm/cseg/inputdata/lnd/clm2/surfdata_map/README_c141219 - call abort() - end if - end if - end do - end if - - end do - - end subroutine lookup_and_check_err - -end subroutine mkurbanpar -!------------------------------------------------------------------------------ - -end module mkurbanparMod diff --git a/tools/mksurfdata_map/src/mkutilsMod.F90 b/tools/mksurfdata_map/src/mkutilsMod.F90 deleted file mode 100644 index 43e779745b..0000000000 --- a/tools/mksurfdata_map/src/mkutilsMod.F90 +++ /dev/null @@ -1,197 +0,0 @@ -module mkutilsMod -!----------------------------------------------------------------------- -!BOP -! -! !MODULE: mkutils -! -! !DESCRIPTION: -! General-purpose utilities for mksurfdata_map -! -! -! !USES: - use shr_kind_mod, only : r8 => shr_kind_r8 - - implicit none - private -! -! !PUBLIC MEMBER FUNCTIONS: - public :: normalize_classes_by_gcell ! renormalize array so values are given as % of total grid cell area - public :: slightly_below - public :: slightly_above -! -! -! !REVISION HISTORY: -! Author: Bill Sacks -! -!EOP -!------------------------------------------------------------------------------ -contains - -!------------------------------------------------------------------------------ -!BOP -! -! !IROUTINE: normalize_classes_by_gcell -! -! !INTERFACE: -subroutine normalize_classes_by_gcell(classes_pct_tot, sums, classes_pct_gcell) -! -! !DESCRIPTION: -! Renormalizes an array (gcell x class) so that values are given as % of total grid cell area -! -! Specifically: Given (1) an array specifying the % cover of different classes, as a % of -! some total ('classes_pct_tot'), and (2) a vector giving these totals ('sums'), expressed -! as % of grid cell area: Returns an array ('classes_pct_gcell') of the same -! dimensionality as classes_pct_tot, where the values now give the % cover of each class -! as a % of total grid cell area. -! -! The size of 'sums' should match the size of the first dimension in 'classes_pct_tot' and -! 'classes_pct_gcell' -! -! For example, if classes_pct_tot(n,i) gives the % of the urban area in grid cell n that is -! in urban class #i, and sums(n) gives the % of grid cell n that is urban, then -! classes_pct_gcell(n,i) will give the % of the total area of grid cell n that is in urban -! class #i. -! -! !USES: -! -! !ARGUMENTS: - implicit none - real(r8), intent(in) :: classes_pct_tot(:,:) ! % cover of classes as % of total - real(r8), intent(in) :: sums(:) ! totals, as % of grid cell - real(r8), intent(out):: classes_pct_gcell(:,:) ! % cover of classes as % of grid cell -! -! !REVISION HISTORY: -! Author: Bill Sacks -! -! -! !LOCAL VARIABLES: -!EOP - integer :: n, n_max - - character(len=*), parameter :: subname = "normalize_classes_by_gcell" -!------------------------------------------------------------------------------ - - ! Error-check inputs - - n_max = size(sums) - if (size(classes_pct_tot, 1) /= n_max .or. & - size(classes_pct_gcell, 1) /= n_max) then - write(6,*) subname//' ERROR: array size mismatch' - write(6,*) 'size(sums) = ', n_max - write(6,*) 'size(classes_pct_tot, 1) = ', size(classes_pct_tot, 1) - write(6,*) 'size(classes_pct_gcell, 1) = ', size(classes_pct_gcell, 1) - call abort() - end if - - if (size(classes_pct_tot, 2) /= size(classes_pct_gcell, 2)) then - write(6,*) subname//' ERROR: array size mismatch' - write(6,*) 'size(classes_pct_tot, 2) = ', size(classes_pct_tot, 2) - write(6,*) 'size(classes_pct_gcell, 2) = ', size(classes_pct_gcell, 2) - call abort() - end if - - ! Do the work - - do n = 1, n_max - classes_pct_gcell(n,:) = classes_pct_tot(n,:) * (sums(n)/100._r8) - end do -end subroutine normalize_classes_by_gcell -!------------------------------------------------------------------------------ - -!------------------------------------------------------------------------------ -!BOP -! -! !IROUTINE: slightly_below -! -! !INTERFACE: -logical function slightly_below(a, b, eps) -! -! !DESCRIPTION: -! Returns true if a is slightly below b; false if a is significantly below b or if a is -! greater than or equal to b -! -! !USES: -! -! !ARGUMENTS: - implicit none - real(r8), intent(in) :: a - real(r8), intent(in) :: b - - ! if provided, eps gives the relative error allowed for checking the "slightly" - ! condition; if not provided, the tolerance defaults to the value given by eps_default - real(r8), intent(in), optional :: eps -! -! !REVISION HISTORY: -! Author: Bill Sacks -! -! -! !LOCAL VARIABLES: -!EOP - real(r8) :: l_eps - real(r8), parameter :: eps_default = 1.e-15_r8 ! default relative error tolerance -!------------------------------------------------------------------------------ - - if (present(eps)) then - l_eps = eps - else - l_eps = eps_default - end if - - if (a < b .and. (b - a)/b < l_eps) then - slightly_below = .true. - else - slightly_below = .false. - end if - -end function slightly_below -!------------------------------------------------------------------------------ - -!------------------------------------------------------------------------------ -!BOP -! -! !IROUTINE: slightly_above -! -! !INTERFACE: -logical function slightly_above(a, b, eps) -! -! !DESCRIPTION: -! Returns true if a is slightly above b; false if a is significantly above b or if a is -! less than or equal to b -! -! !USES: -! -! !ARGUMENTS: - implicit none - real(r8), intent(in) :: a - real(r8), intent(in) :: b - - ! if provided, eps gives the relative error allowed for checking the "slightly" - ! condition; if not provided, the tolerance defaults to the value given by eps_default - real(r8), intent(in), optional :: eps -! -! !REVISION HISTORY: -! Author: Bill Sacks -! -! -! !LOCAL VARIABLES: -!EOP - real(r8) :: l_eps - real(r8), parameter :: eps_default = 1.e-15_r8 ! default relative error tolerance -!------------------------------------------------------------------------------ - - if (present(eps)) then - l_eps = eps - else - l_eps = eps_default - end if - - if (a > b .and. (a - b)/b < l_eps) then - slightly_above = .true. - else - slightly_above = .false. - end if - -end function slightly_above -!------------------------------------------------------------------------------ - -end module mkutilsMod diff --git a/tools/mksurfdata_map/src/mkvarctl.F90 b/tools/mksurfdata_map/src/mkvarctl.F90 deleted file mode 100644 index 864291ae07..0000000000 --- a/tools/mksurfdata_map/src/mkvarctl.F90 +++ /dev/null @@ -1,90 +0,0 @@ -module mkvarctl - -!----------------------------------------------------------------------- -!BOP -! -! !MODULE: mkvarctl -! -! !DESCRIPTION: -! Module containing control variables -! -! !USES: - use shr_kind_mod, only: r8 => shr_kind_r8 -! -! !PUBLIC TYPES: - implicit none - private - save -! - real(r8), public, parameter :: spval = 1.e36 ! special value - integer, public, parameter :: ispval = -9999 ! special value - - logical, public :: outnc_large_files ! output files in 64-bit format for large files - logical, public :: outnc_double ! output ALL data in files as 64-bit - integer, public :: outnc_dims = 2 ! only applicable to lat/lon grids - logical, public :: outnc_1d ! true => output file is 1d - logical, public :: outnc_vic ! true => output VIC fields - logical, public :: outnc_3dglc ! true => output 3D glacier fields - - character(len= 32), public :: mksrf_gridnm = ' ' ! name of grid to use on output file - character(len=256), public :: mksrf_fgrid = ' ' ! land grid file name to use - character(len=256), public :: mksrf_gridtype = ' ' ! land gridtype, global or reg - character(len=256), public :: mksrf_fvegtyp = ' ' ! vegetation data file name - character(len=256), public :: mksrf_fhrvtyp = ' ' ! harvest data file name - character(len=256), public :: mksrf_fsoitex = ' ' ! soil texture data file name - character(len=256), public :: mksrf_forganic = ' ' ! organic matter data file name - character(len=256), public :: mksrf_fsoicol = ' ' ! soil color data file name - character(len=256), public :: mksrf_fabm = ' ' ! ag fire peak month and - character(len=256), public :: mksrf_fpeat = ' ' ! peatlands and - character(len=256), public :: mksrf_fsoildepth = ' ' ! soil depth file name - character(len=256), public :: mksrf_fgdp = ' ' ! gdp data file names - character(len=256), public :: mksrf_flakwat = ' ' ! inland lake data file name - character(len=256), public :: mksrf_fwetlnd = ' ' ! inland wetlands data file name - character(len=256), public :: mksrf_furban = ' ' ! urban data file name - character(len=256), public :: mksrf_fglacier = ' ' ! glacier data file name - character(len=256), public :: mksrf_fglacierregion = ' ' ! glacier region data file name - character(len=256), public :: mksrf_furbtopo = ' ' ! urban topography data file name - character(len=256), public :: mksrf_fmax = ' ' ! fmax data file name - character(len=256), public :: mksrf_flai = ' ' ! lai data filename - character(len=256), public :: mksrf_fdynuse = ' ' ! ascii file containing names of dynamic land use files - character(len=256), public :: mksrf_fvocef = ' ' ! VOC Emission Factor data file name - character(len=256), public :: mksrf_ftopostats = ' ' ! topography statistics data file name - character(len=256), public :: mksrf_fvic = ' ' ! VIC parameters data file name - - integer , public :: numpft = 16 ! number of plant types - - character(len=256), public :: map_fpft = ' ' ! Mapping file for PFT - character(len=256), public :: map_flakwat = ' ' ! Mapping file for lake water - character(len=256), public :: map_fwetlnd = ' ' ! Mapping file for wetland water - character(len=256), public :: map_fglacier = ' ' ! Mapping file for glacier - character(len=256), public :: map_fglacierregion = ' ' ! Mapping file for glacier region - character(len=256), public :: map_fsoitex = ' ' ! Mapping file for soil texture - character(len=256), public :: map_fsoicol = ' ' ! Mapping file for soil color - character(len=256), public :: map_fabm = ' ' ! Mapping file: ag fire... - character(len=256), public :: map_fpeat = ' ' ! Mapping file: peatlands - character(len=256), public :: map_fsoildepth = ' ' ! Mapping file: soil depth - character(len=256), public :: map_fgdp = ' ' ! Mapping file: gdp - character(len=256), public :: map_furban = ' ' ! Mapping file for urban - character(len=256), public :: map_furbtopo = ' ' ! Mapping file for urban topography - character(len=256), public :: map_fmax = ' ' ! Mapping file for soil frac max - character(len=256), public :: map_forganic = ' ' ! Mapping file for organic soil - character(len=256), public :: map_fvocef = ' ' ! Mapping file for VOC emission factors - character(len=256), public :: map_flai = ' ' ! Mapping file for LAI - character(len=256), public :: map_fharvest = ' ' ! Mapping file for harvesting - character(len=256), public :: map_ftopostats = ' ' ! Mapping file for topography statistics - character(len=256), public :: map_fvic = ' ' ! Mapping file for VIC parameters - character(len=80) , public :: gitdescribe = ' ' ! Description of model version from git -! -! Variables to override data read in with -! (all_urban is mostly for single-point mode, but could be used for sensitivity studies) -! - logical, public :: all_urban ! output ALL data as 100% covered in urban - logical, public :: no_inlandwet ! set wetland to 0% over land; wetland will only be used for ocean points -! -! !REVISION HISTORY: -! Created by Mariana Vertenstein 11/04 -! -!EOP -!----------------------------------------------------------------------- - -end module mkvarctl diff --git a/tools/mksurfdata_map/src/mkvarpar.F90 b/tools/mksurfdata_map/src/mkvarpar.F90 deleted file mode 100644 index a8a01d2da2..0000000000 --- a/tools/mksurfdata_map/src/mkvarpar.F90 +++ /dev/null @@ -1,32 +0,0 @@ -module mkvarpar - -!----------------------------------------------------------------------- -!BOP -! -! !MODULE: clm_varpar -! -! !DESCRIPTION: -! Module containing CLM parameters -! -! !USES: - use shr_kind_mod, only: r8 => shr_kind_r8 - use shr_const_mod, only: SHR_CONST_REARTH -! -! !PUBLIC TYPES: - implicit none - save -! - integer, parameter :: nlevsoi = 10 ! number of soil layers - integer, parameter :: numstdpft = 16! number of standard PFT types - integer, parameter :: numstdcft = 2 ! of the number of standard PFT types, how many are crop (CFT) - integer, parameter :: noveg = 0 ! value for non-vegetated pft - integer, parameter :: numsolar = 2 ! number of solar types (Direct,Diffuse) - integer, parameter :: numrad = 2 ! number of solar bands (VIS,NIR) - real(r8),parameter :: elev_thresh = 2600._r8 ! elevation threshold for screening urban areas - real(r8),parameter :: re = SHR_CONST_REARTH*0.001 - -! -!EOP -!----------------------------------------------------------------------- - -end module mkvarpar diff --git a/tools/mksurfdata_map/src/mkvocefMod.F90 b/tools/mksurfdata_map/src/mkvocefMod.F90 deleted file mode 100644 index 03d9dddd3f..0000000000 --- a/tools/mksurfdata_map/src/mkvocefMod.F90 +++ /dev/null @@ -1,209 +0,0 @@ -module mkvocefMod -!----------------------------------------------------------------------- -!BOP -! -! !MODULE: mkvocMod -! -! !DESCRIPTION: -! Make VOC percentage emissions for surface dataset -! -! !REVISION HISTORY: -! Author: Erik Kluzek -! -!----------------------------------------------------------------------- -! !USES: - use shr_kind_mod, only : r8 => shr_kind_r8 - use shr_sys_mod , only : shr_sys_flush - use mkdomainMod , only : domain_checksame - - implicit none - private - -! !PUBLIC MEMBER FUNCTIONS: - public :: mkvocef ! Get the percentage emissions for VOC for different - ! land cover types -!EOP - -contains - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: mkvocef -! -! !INTERFACE: -subroutine mkvocef(ldomain, mapfname, datfname, ndiag, & - ef_btr_o, ef_fet_o, ef_fdt_o, ef_shr_o, ef_grs_o, ef_crp_o) -! -! !DESCRIPTION: -! make volatile organic coumpunds (VOC) emission factors. -! -! !USES: - use mkdomainMod, only : domain_type, domain_clean, domain_read - use mkgridmapMod - use mkvarpar - use mkvarctl - use mkncdio -! -! !ARGUMENTS: - implicit none - type(domain_type) , intent(in) :: ldomain - character(len=*) , intent(in) :: mapfname ! input mapping file name - character(len=*) , intent(in) :: datfname ! input data file name - integer , intent(in) :: ndiag ! unit number for diagnostic output - real(r8) , intent(out):: ef_btr_o(:) ! output grid: EFs for broadleaf trees - real(r8) , intent(out):: ef_fet_o(:) ! output grid: EFs for fineleaf evergreen - real(r8) , intent(out):: ef_fdt_o(:) ! output grid: EFs for fineleaf deciduous - real(r8) , intent(out):: ef_shr_o(:) ! output grid: EFs for shrubs - real(r8) , intent(out):: ef_grs_o(:) ! output grid: EFs for grasses - real(r8) , intent(out):: ef_crp_o(:) ! output grid: EFs for crops -! -! !CALLED FROM: -! subroutine mksrfdat in module mksrfdatMod -! -! !REVISION HISTORY: -! Author: Colette L. Heald -! 17 Jul 2007 F Vitt -- updated to pftintdat06_clm3_5_05 and corrected indexing of ef_*_i arrarys -! -!EOP -! -! !LOCAL VARIABLES: - type(gridmap_type) :: tgridmap - type(domain_type) :: tdomain ! local domain - real(r8), allocatable :: ef_btr_i(:) ! input grid: EFs for broadleaf trees - real(r8), allocatable :: ef_fet_i(:) ! input grid: EFs for fineleaf evergreen - real(r8), allocatable :: ef_fdt_i(:) ! input grid: EFs for fineleaf deciduous - real(r8), allocatable :: ef_shr_i(:) ! input grid: EFs for shrubs - real(r8), allocatable :: ef_grs_i(:) ! input grid: EFs for grasses - real(r8), allocatable :: ef_crp_i(:) ! input grid: EFs for crops - real(r8), allocatable :: frac_dst(:) ! output fractions - real(r8), allocatable :: mask_r8(:) ! float of tdomain%mask - real(r8) :: sum_fldo ! global sum of dummy input fld - real(r8) :: sum_fldi ! global sum of dummy input fld - integer :: k,n,no,ni,ns_o,ns_i ! indices - integer :: ncid,dimid,varid ! input netCDF id's - integer :: ier ! error status - real(r8) :: relerr = 0.00001_r8 ! max error: sum overlap wts ne 1 - character(len=32) :: subname = 'mkvocef' -!----------------------------------------------------------------------- - - write (6,*) 'Attempting to make VOC emission factors .....' - call shr_sys_flush(6) - - ns_o = ldomain%ns - - ! ----------------------------------------------------------------- - ! Read input Emission Factors - ! ----------------------------------------------------------------- - - ! Obtain input grid info, read local fields - - call domain_read(tdomain,datfname) - ns_i = tdomain%ns - allocate(ef_btr_i(ns_i), ef_fet_i(ns_i), ef_fdt_i(ns_i), & - ef_shr_i(ns_i), ef_grs_i(ns_i), ef_crp_i(ns_i), & - frac_dst(ns_o), stat=ier) - if (ier/=0) call abort() - - write (6,*) 'Open VOC file: ', trim(datfname) - call check_ret(nf_open(datfname, 0, ncid), subname) - call check_ret(nf_inq_varid (ncid, 'ef_btr', varid), subname) - call check_ret(nf_get_var_double(ncid, varid, ef_btr_i), subname) - call check_ret(nf_inq_varid (ncid, 'ef_fet', varid), subname) - call check_ret(nf_get_var_double(ncid, varid, ef_fet_i), subname) - call check_ret(nf_inq_varid (ncid, 'ef_fdt', varid), subname) - call check_ret(nf_get_var_double(ncid, varid, ef_fdt_i), subname) - call check_ret(nf_inq_varid (ncid, 'ef_shr', varid), subname) - call check_ret(nf_get_var_double(ncid, varid, ef_shr_i), subname) - call check_ret(nf_inq_varid (ncid, 'ef_grs', varid), subname) - call check_ret(nf_get_var_double(ncid, varid, ef_grs_i), subname) - call check_ret(nf_inq_varid (ncid, 'ef_crp', varid), subname) - call check_ret(nf_get_var_double(ncid, varid, ef_crp_i), subname) - call check_ret(nf_close(ncid), subname) - - ! Area-average percent cover on input grid to output grid - ! and correct according to land landmask - ! Note that percent cover is in terms of total grid area. - - call gridmap_mapread(tgridmap, mapfname ) - - ! Error checks for domain and map consistencies - - call domain_checksame( tdomain, ldomain, tgridmap ) - - ! Obtain frac_dst - call gridmap_calc_frac_dst(tgridmap, tdomain%mask, frac_dst) - - ! Do mapping from input to output grid - - call gridmap_areaave_srcmask(tgridmap, ef_btr_i, ef_btr_o, nodata=0._r8, mask_src=tdomain%mask, frac_dst=frac_dst) - call gridmap_areaave_srcmask(tgridmap, ef_fet_i, ef_fet_o, nodata=0._r8, mask_src=tdomain%mask, frac_dst=frac_dst) - call gridmap_areaave_srcmask(tgridmap, ef_fdt_i, ef_fdt_o, nodata=0._r8, mask_src=tdomain%mask, frac_dst=frac_dst) - call gridmap_areaave_srcmask(tgridmap, ef_shr_i, ef_shr_o, nodata=0._r8, mask_src=tdomain%mask, frac_dst=frac_dst) - call gridmap_areaave_srcmask(tgridmap, ef_grs_i, ef_grs_o, nodata=0._r8, mask_src=tdomain%mask, frac_dst=frac_dst) - call gridmap_areaave_srcmask(tgridmap, ef_crp_i, ef_crp_o, nodata=0._r8, mask_src=tdomain%mask, frac_dst=frac_dst) - - ! Check for conservation - - do no = 1, ns_o - if ( ef_btr_o(no) < 0._r8 ) then - write (6,*) 'MKVOCEF error: EF btr = ',ef_btr_o(no), & - ' is negative for no = ',no - call abort() - end if - if ( ef_fet_o(no) < 0._r8 ) then - write (6,*) 'MKVOCEF error: EF fet = ',ef_fet_o(no), & - ' is negative for no = ',no - call abort() - end if - if ( ef_fdt_o(no) < 0._r8 ) then - write (6,*) 'MKVOCEF error: EF fdt = ',ef_fdt_o(no), & - ' is negative for no = ',no - call abort() - end if - if ( ef_shr_o(no) < 0._r8 ) then - write (6,*) 'MKVOCEF error: EF shr = ',ef_shr_o(no), & - ' is negative for no = ',no - call abort() - end if - if ( ef_grs_o(no) < 0._r8 ) then - write (6,*) 'MKVOCEF error: EF grs = ',ef_grs_o(no), & - ' is negative for no = ',no - call abort() - end if - if ( ef_crp_o(no) < 0._r8 ) then - write (6,*) 'MKVOCEF error: EF crp = ',ef_crp_o(no), & - ' is negative for no = ',no - call abort() - end if - enddo - - ! ----------------------------------------------------------------- - ! Error check1 - ! Compare global sum fld_o to global sum fld_i. - ! ----------------------------------------------------------------- - - ! Global sum of output field -- must multiply by fraction of - ! output grid that is land as determined by input grid - - allocate(mask_r8(ns_i), stat=ier) - if (ier/=0) call abort() - mask_r8 = tdomain%mask - call gridmap_check( tgridmap, mask_r8, frac_dst, subname ) - - write (6,*) 'Successfully made VOC Emission Factors' - write (6,*) - call shr_sys_flush(6) - - ! Deallocate dynamic memory - - deallocate ( ef_btr_i, ef_fet_i, ef_fdt_i, & - ef_shr_i, ef_grs_i, ef_crp_i, frac_dst, mask_r8 ) - call domain_clean(tdomain) - call gridmap_clean(tgridmap) - -end subroutine mkvocef - -!----------------------------------------------------------------------- - -end module mkvocefMod diff --git a/tools/mksurfdata_map/src/shr_file_mod.F90 b/tools/mksurfdata_map/src/shr_file_mod.F90 deleted file mode 100644 index a5e8d1987d..0000000000 --- a/tools/mksurfdata_map/src/shr_file_mod.F90 +++ /dev/null @@ -1,1023 +0,0 @@ -!BOP =========================================================================== -! -! !MODULE: shr_file_mod.F90 --- Module to handle various file utilily functions. -! -! !DESCRIPTION: -! -! Miscilaneous methods to handle file and directory utilities as well as FORTRAN -! unit control. Also put/get local files into/from archival location -! -! File utilites used with CCSM Message passing: -! -! shr_file_stdio is the main example here, it changes the working directory, -! changes stdin and stdout to a given filename. -! -! This is needed because some implementations of MPI with MPMD so that -! each executable can run in a different working directory and redirect -! output to different files. -! -! File name archival convention, eg. -! call shr_file_put(rcode,"foo","mss:/USER/foo",rtpd=3650) -! is extensible -- the existence of the option file name prefix, eg. "mss:", -! and optional arguments, eg. rtpd-3650 can be used to access site-specific -! storage devices. Based on CCM (atmosphere) getfile & putfile routines, but -! intended to be a more extensible, shared code. -! -! !REVISION HISTORY: -! 2006-05-08 E. Kluzek, Add in shr_file_mod and getUnit, freeUnif methods. -! 2000-??-?? B. Kauffman, original version circa 2000 -! -! !INTERFACE: ------------------------------------------------------------------ - -MODULE shr_file_mod - -! !USES: - - use shr_kind_mod ! defines kinds - use shr_sys_mod ! system calls - use shr_log_mod, only: s_loglev => shr_log_Level - use shr_log_mod, only: s_logunit => shr_log_Unit - - IMPLICIT none - - PRIVATE ! By default everything is private to this module - -! !PUBLIC TYPES: - - ! no public types - -! !PUBLIC MEMBER FUNCTIONS: - - public :: shr_file_put ! Put a file to an archive location - public :: shr_file_get ! Get a file from an archive location - public :: shr_file_queryPrefix ! Get prefix type for a filename - public :: shr_file_getUnit ! Get a logical unit for reading or writing - public :: shr_file_freeUnit ! Free a logical unit - public :: shr_file_stdio ! change dir and stdin and stdout - public :: shr_file_chDir ! change current working directory - public :: shr_file_dirio ! change stdin and stdout - public :: shr_file_chStdIn ! change stdin (attach to a file) - public :: shr_file_chStdOut ! change stdout (attach to a file) - public :: shr_file_setIO ! open a log file from namelist - public :: shr_file_setLogUnit ! Reset the log unit number - public :: shr_file_setLogLevel ! Reset the logging debug level - public :: shr_file_getLogUnit ! Get the log unit number - public :: shr_file_getLogLevel ! Get the logging debug level - -! !PUBLIC DATA MEMBERS: - - ! Integer flags for recognized prefixes on file get/put operations - integer(SHR_KIND_IN), parameter, public :: shr_file_noPrefix = 0 ! no recognized prefix - integer(SHR_KIND_IN), parameter, public :: shr_file_nullPrefix = 1 ! null: - integer(SHR_KIND_IN), parameter, public :: shr_file_cpPrefix = 2 ! cp: - integer(SHR_KIND_IN), parameter, public :: shr_file_mssPrefix = 3 ! mss: - integer(SHR_KIND_IN), parameter, public :: shr_file_hpssPrefix = 4 ! hpss: - -!EOP - !--- unit numbers, users can ask for unit numbers from 0 to min, but getUnit - !--- won't give a unit below min, users cannot ask for unit number above max - !--- for backward compatability. - !--- eventually, recommend min as hard lower limit (tcraig, 9/2007) - integer(SHR_KIND_IN),parameter :: shr_file_minUnit = 10 ! Min unit number to give - integer(SHR_KIND_IN),parameter :: shr_file_maxUnit = 99 ! Max unit number to give - logical, save :: UnitTag(0:shr_file_maxUnit) = .false. ! Logical units in use - -!=============================================================================== -CONTAINS -!=============================================================================== - -!=============================================================================== -!BOP =========================================================================== -! -! !IROUTINE: shr_file_put -- Put a file to an archival location. -! -! !DESCRIPTION: -! a generic, extensible put-local-file-into-archive routine -! USAGE: -! call shr_file_put(rcode,"foo","/home/user/foo") -! if ( rcode /= 0 ) call shr_sys_abort( "error copying foo" ) -! call shr_file_put(rcode,"foo","cp:/home/user/foo",remove=.true.) -! if ( rcode /= 0 ) call shr_sys_abort( "error copying foo" ) -! call shr_file_put(rcode,"foo","mss:/USER/foo",rtpd=3650) -! if ( rcode /= 0 ) call shr_sys_abort( "error archiving foo to MSS" ) -! -! !INTERFACE: ------------------------------------------------------------------ - -SUBROUTINE shr_file_put(rcode,loc_fn,rem_fn,passwd,rtpd,async,remove) - - implicit none - -! !INPUT/OUTPUT PARAMETERS: - - integer(SHR_KIND_IN),intent(out) :: rcode ! return code (non-zero -- error) - character(*), intent(in) :: loc_fn ! local filename - character(*), intent(in) :: rem_fn ! remote filename - character(*), intent(in),optional :: passwd ! password - integer(SHR_KIND_IN),intent(in),optional :: rtpd ! MSS retention period - logical, intent(in),optional :: async ! true <=> asynchronous put - logical, intent(in),optional :: remove ! true <=> rm after put - -!EOP - - !----- local ----- - integer(SHR_KIND_IN) :: rtpd2 ! MSS retention period - logical :: remove2 ! true <=> rm after put - logical :: async2 ! true <=> asynchronous put - character(SHR_KIND_CL) :: passwd2 ! password - character(SHR_KIND_CL) :: rfn ! rem_fn without the destination prefix - character(SHR_KIND_CL) :: cmd ! command sent to system call - integer(SHR_KIND_IN) :: prefix ! remote file prefix type - - !----- formats ----- - character(*),parameter :: subName = '(shr_file_put) ' - character(*),parameter :: F00 = "('(shr_file_put) ',4a)" - character(*),parameter :: F01 = "('(shr_file_put) ',a,i3,2a)" - character(*),parameter :: F02 = "(a,i4)" - -!------------------------------------------------------------------------------- -! Notes: -! - On some machines the system call will not return a valid error code -! - when things are sent asynchronously, there probably won't be a error code -! returned. -!------------------------------------------------------------------------------- - - remove2 =.false. ; if ( PRESENT(remove )) remove2 = remove - async2 =.true. ; if ( PRESENT(async )) async2 = async - passwd2 = " " ; if ( PRESENT(passwd )) passwd2 = passwd - rtpd2 = 365 ; if ( PRESENT(rtpd )) rtpd2 = rtpd - rcode = 0 - - if ( trim(rem_fn) == trim(loc_fn) ) then - !------------------------------------------------------ - ! (remote file name) == (local file name) => do nothing - !------------------------------------------------------ - cmd = 'do nothing: remote file = local file = '//trim(loc_fn) - rcode = 0 - else if ( prefix == shr_file_cpPrefix .or. prefix == shr_file_noPrefix )then - !------------------------------------------------------ - ! put via unix cp - !------------------------------------------------------ - rfn = rem_fn - if ( rem_fn(1:3) == "cp:") rfn = rem_fn(4:len_trim(rem_fn)) -#if defined(CATAMOUNT) - call shr_jlcp(trim(loc_fn),len_trim(loc_fn),trim(rfn),len_trim(rfn),rcode) - if (remove2) call unlink(trim(loc_fn)) - if (async2 .and. s_loglev > 0) write(s_logunit,F00) 'Error: asynchronous copy not supported.' - cmd = 'shr_jlcp -f '//trim(loc_fn)//' '//trim(rfn) - rcode = 0 -#else - cmd = '/bin/cp -f '//trim(loc_fn)//' '//trim(rfn) - if (remove2) cmd = trim(cmd)//' && /bin/rm -f '//trim(loc_fn) - if (async2 ) cmd = trim(cmd)//' & ' - call shr_sys_system(trim(cmd),rcode) -#endif - else if ( prefix == shr_file_mssPrefix )then - !------------------------------------------------------ - ! put onto NCAR's MSS - !------------------------------------------------------ - if (rtpd2 > 9999) rtpd2 = 9999 - write(cmd,F02) '/usr/local/bin/msrcp -period ',rtpd2 - if (async2 .and. (.not. remove2) ) cmd = trim(cmd)//' -async ' - if (len_trim(passwd2) > 0 ) cmd = trim(cmd)//' -wpwd '//trim(passwd) - cmd = trim(cmd)//' '//trim(loc_fn)//' '//trim(rem_fn) - if (remove2) cmd = trim(cmd)//' && /bin/rm -f '//trim(loc_fn) - if (async2 .and. remove2 ) cmd = trim(cmd)//' & ' - call shr_sys_system(trim(cmd),rcode) - else if ( prefix == shr_file_hpssPrefix )then - !------------------------------------------------------ - ! put onto LANL's hpss - !------------------------------------------------------ - rcode = -1 - cmd = 'rem_fn='//trim(rem_fn)//' loc_fn='//trim(loc_fn) - write(s_logunit,F00) 'ERROR: hpss option not yet implemented' - call shr_sys_abort( subName//'ERROR: hpss option not yet implemented' ) - else if ( prefix == shr_file_nullPrefix )then - ! do nothing - cmd = "null prefix => no file archival, do nothing" - rcode = 0 - end if - - if (s_loglev > 0) write(s_logunit,F01) 'rcode =',rcode,' cmd = ', trim(cmd) - -END SUBROUTINE shr_file_put - -!=============================================================================== -!BOP =========================================================================== -! -! !IROUTINE: shr_file_get -- Get a file from archival location. -! -! !DESCRIPTION: -! a generic, extensible get-local-file-from-archive routine -! -! USAGE: -! call shr_file_get(rcode,"foo","/home/user/foo") -! if ( rcode /= 0 ) call shr_sys_abort( "error getting file foo" ) -! call shr_file_get(rcode,"foo","cp:/home/user/foo",remove=.true.) -! if ( rcode /= 0 ) call shr_sys_abort( "error getting file foo" ) -! call shr_file_get(rcode,"foo","mss:/USER/foo",clobber=.true.) -! if ( rcode /= 0 ) call shr_sys_abort( "error getting file foo from MSS" ) -! -! !INTERFACE: ------------------------------------------------------------------ - -SUBROUTINE shr_file_get(rcode,loc_fn,rem_fn,passwd,async,clobber) - - implicit none - -! !INPUT/OUTPUT PARAMETERS: - - integer(SHR_KIND_IN),intent(out) :: rcode ! return code (non-zero means error) - character(*) ,intent(in) :: loc_fn ! local filename - character(*) ,intent(in) :: rem_fn ! remote filename - character(*) ,intent(in),optional :: passwd ! password - logical ,intent(in),optional :: async ! true <=> asynchronous get - logical ,intent(in),optional :: clobber ! true <=> clobber existing file - -!EOP - - !----- local ----- - logical :: async2 ! true <=> asynchronous get - logical :: clobber2 ! true <=> clobber existing file - logical :: exists ! true <=> local file a ready exists - character(SHR_KIND_CL) :: passwd2 ! password - character(SHR_KIND_CL) :: rfn ! rem_fn without the destination prefix - character(SHR_KIND_CL) :: cmd ! command sent to system call - integer(SHR_KIND_IN) :: prefix ! remote file prefix type - - !----- formats ----- - character(*),parameter :: subName = '(shr_file_get) ' - character(*),parameter :: F00 = "('(shr_file_get) ',4a)" - character(*),parameter :: F01 = "('(shr_file_get) ',a,i3,2a)" - -!------------------------------------------------------------------------------- -! Notes: -! - On some machines the system call will not return a valid error code -! - When things are sent asynchronously, there probably won't be a error code -! returned. -!------------------------------------------------------------------------------- - - passwd2 = " " ; if (PRESENT(passwd )) passwd2 = passwd - async2 = .false. ; if (PRESENT(async )) async2 = async - clobber2 = .false. ; if (PRESENT(clobber)) clobber2 = clobber - rcode = 0 - - inquire(file=trim(loc_fn),exist=exists) - prefix = shr_file_queryPrefix( rem_fn ) - - if ( exists .and. .not. clobber2 ) then - !------------------------------------------------------ - ! (file exists) and (don't clobber) => do nothing - !------------------------------------------------------ - cmd = 'do nothing: file exists & no-clobber for '//trim(loc_fn) - rcode = 0 - else if ( trim(rem_fn) == trim(loc_fn) ) then - !------------------------------------------------------ - ! (remote file name) == (local file name) => do nothing - !------------------------------------------------------ - cmd = 'do nothing: remote file = local file for '//trim(loc_fn) - rcode = 0 - else if ( prefix == shr_file_cpPrefix .or. prefix == shr_file_noPrefix )then - !------------------------------------------------------ - ! get via unix cp - !------------------------------------------------------ - rfn = rem_fn ! remove prefix from this temp file name - if (rem_fn(1:3) == "cp:") rfn = rem_fn(4:len_trim(rem_fn)) -#if defined(CATAMOUNT) - call shr_jlcp(trim(rfn),len(trim(rfn)),trim(loc_fn),len(trim(loc_fn)),rcode) - if (async2.and.s_loglev>0) write(s_logunit,F00) 'Error: asynchronous copy not supported.' - cmd = 'shr_jlcp -f '//trim(rfn)//' '//trim(loc_fn) - rcode = 0 -#else - cmd = '/bin/cp -f '//trim(rfn)//' '//trim(loc_fn) - if (async2) cmd = trim(cmd)//' & ' - call shr_sys_system(trim(cmd),rcode) -#endif - else if ( prefix == shr_file_mssPrefix )then - !------------------------------------------------------ - ! get from NCAR's MSS - !------------------------------------------------------ - cmd = '/usr/local/bin/msrcp ' - if (async2) cmd = trim(cmd)//' -async ' - cmd = trim(cmd)//' '//trim(rem_fn)//' '//trim(loc_fn) - call shr_sys_system(trim(cmd),rcode) - else if ( prefix == shr_file_hpssPrefix )then - !------------------------------------------------------ - ! get from LANL's hpss - !------------------------------------------------------ - rcode = -1 - cmd = 'rem_fn='//trim(rem_fn)//' loc_fn='//trim(loc_fn) - write(s_logunit,F00) 'ERROR: hpss option not yet implemented' - call shr_sys_abort( subName//'ERROR: hpss option not yet implemented' ) - else if ( prefix == shr_file_nullPrefix )then - ! do nothing - cmd = "null prefix => no file retrieval, do nothing" - rcode = 0 - end if - - if (s_loglev > 0) write(s_logunit,F01) 'rcode =',rcode,' cmd = ', trim(cmd) - -END SUBROUTINE shr_file_get - -!=============================================================================== -!BOP =========================================================================== -! -! !IROUTINE: shr_file_queryPrefix -- Get the prefix type from a filepath. -! -! !DESCRIPTION: -! -! !INTERFACE: ------------------------------------------------------------------ - -integer(SHR_KIND_IN) FUNCTION shr_file_queryPrefix( filepath, prefix ) - - implicit none - -! !INPUT/OUTPUT PARAMETERS: - - character(*), intent(in) :: filepath ! Input filepath - character(*), intent(out), optional :: prefix ! Output prefix description - -!EOP - - !----- local ----- - -!------------------------------------------------------------------------------- -! Notes: -!------------------------------------------------------------------------------- - - if ( filepath(1:5) == "null:" )then - shr_file_queryPrefix = shr_file_nullPrefix - if ( present(prefix) ) prefix = "null:" - else if( filepath(1:3) == "cp:" )then - shr_file_queryPrefix = shr_file_cpPrefix - if ( present(prefix) ) prefix = "cp:" - else if( filepath(1:4) == "mss:" )then - shr_file_queryPrefix = shr_file_mssPrefix - if ( present(prefix) ) prefix = "mss:" - else if( filepath(1:5) == "hpss:" )then - shr_file_queryPrefix = shr_file_hpssPrefix - if ( present(prefix) ) prefix = "hpss:" - else - shr_file_queryPrefix = shr_file_noPrefix - if ( present(prefix) ) prefix = "" - end if - -END FUNCTION shr_file_queryPrefix - -!=============================================================================== -!BOP =========================================================================== -! -! !IROUTINE: shr_file_getUnit -- Get a free FORTRAN unit number -! -! !DESCRIPTION: Get the next free FORTRAN unit number. -! -! !REVISION HISTORY: -! 2005-Dec-14 - E. Kluzek - creation -! -! !INTERFACE: ------------------------------------------------------------------ - -INTEGER FUNCTION shr_file_getUnit ( unit ) - - implicit none - -! !INPUT/OUTPUT PARAMETERS: - - integer(SHR_KIND_IN),intent(in),optional :: unit ! desired unit number - -!EOP - - !----- local ----- - integer(SHR_KIND_IN) :: n ! loop index - logical :: opened ! If unit opened or not - - !----- formats ----- - character(*),parameter :: subName = '(shr_file_getUnit) ' - character(*),parameter :: F00 = "('(shr_file_getUnit) ',A,I4,A)" - -!------------------------------------------------------------------------------- -! Notes: -!------------------------------------------------------------------------------- - - if (present (unit)) then - inquire( unit, opened=opened ) - if (unit < 0 .or. unit > shr_file_maxUnit) then - write(s_logunit,F00) 'invalid unit number request:', unit - call shr_sys_abort( 'ERROR: bad input unit number' ) - else if (opened .or. UnitTag(unit) .or. unit == 0 .or. unit == 5 & - .or. unit == 6) then - write(s_logunit,F00) 'unit number ', unit, ' is already in use' - call shr_sys_abort( 'ERROR: Input unit number already in use' ) - else - shr_file_getUnit = unit - UnitTag (unit) = .true. - return - end if - - else - ! --- Choose first available unit other than 0, 5, or 6 ------ - do n=shr_file_maxUnit, shr_file_minUnit, -1 - inquire( n, opened=opened ) - if (n == 5 .or. n == 6 .or. opened) then - cycle - end if - if ( .not. UnitTag(n) ) then - shr_file_getUnit = n - UnitTag(n) = .true. - return - end if - end do - end if - - call shr_sys_abort( subName//': Error: no available units found' ) - -END FUNCTION shr_file_getUnit - -!=============================================================================== -!BOP =========================================================================== -! -! !IROUTINE: shr_file_freeUnit -- Free up a FORTRAN unit number -! -! !DESCRIPTION: Free up the given unit number -! -! !REVISION HISTORY: -! 2005-Dec-14 - E. Kluzek - creation -! -! !INTERFACE: ------------------------------------------------------------------ - -SUBROUTINE shr_file_freeUnit ( unit) - - implicit none - -! !INPUT/OUTPUT PARAMETERS: - - integer(SHR_KIND_IN),intent(in) :: unit ! unit number to be freed - -!EOP - - !----- local ----- - - !----- formats ----- - character(*), parameter :: subName = '(shr_file_freeUnit) ' - character(*), parameter :: F00 = "('(shr_file_freeUnit) ',A,I4,A)" - -!------------------------------------------------------------------------------- -! Notes: -!------------------------------------------------------------------------------- - - if (unit < 0 .or. unit > shr_file_maxUnit) then - if (s_loglev > 0) write(s_logunit,F00) 'invalid unit number request:', unit - else if (unit == 0 .or. unit == 5 .or. unit == 6) then - call shr_sys_abort( subName//': Error: units 0, 5, and 6 must not be freed' ) - else if (UnitTag(unit)) then - UnitTag (unit) = .false. - else - if (s_loglev > 0) write(s_logunit,F00) 'unit ', unit, ' was not in use' - end if - - return - -END SUBROUTINE shr_file_freeUnit - -!=============================================================================== -!BOP =========================================================================== -! -! !IROUTINE: shr_file_stdio -- Change working directory, and redirect stdin/stdout -! -! !DESCRIPTION: -! 1) change the cwd (current working directory) and -! 2) redirect stdin & stdout (units 5 & 6) to named files, -! where the desired cwd & files are specified by namelist file. -! -! Normally this is done to work around limitations in the execution syntax -! of common MPI implementations. For example, SGI's mpirun syntax is not -! flexible enough to allow MPMD models to select different execution -! directories or to redirect stdin & stdout on the command line. -! Such functionality is highly desireable for CCSM purposes. -! ie. mpirun can't handle this: -! unix> cd /usr/tmp/jdoe/csm/case01/atm ; atm < atm.parm > atm.log & -! unix> cd /usr/tmp/jdoe/csm/case01/cpl ; cpl < cpl.parm > cpl.log & -! etc. -! -! ASSUMPTIONS: -! o if the cwd, stdin, or stdout are to be changed, there must be a namelist -! file in the cwd named _stdio.nml where is provided via -! subroutine dummy argument. -! -! !INTERFACE: ------------------------------------------------------------------ - -SUBROUTINE shr_file_stdio(model) - - implicit none - -! !INPUT/OUTPUT PARAMETERS: - - character(*),intent(in) :: model ! used to construct env varible name - -!EOP - - !--- formats --- - character(*),parameter :: subName = '(shr_file_stdio) ' - character(*),parameter :: F00 = "('(shr_file_stdio) ',4a)" - -!------------------------------------------------------------------------------- -! Notes: -!------------------------------------------------------------------------------- - - call shr_file_chdir (model) ! changes cwd - call shr_file_chStdOut(model) ! open units 5 & 6 to named files - call shr_file_chStdIn (model) ! open units 5 & 6 to named files - -END SUBROUTINE shr_file_stdio - -!=============================================================================== -!BOP =========================================================================== -! -! !IROUTINE: shr_file_chdir -- Change working directory. -! -! !DESCRIPTION: -! change the cwd (current working directory), see shr_file_stdio for notes -! -! !INTERFACE: ------------------------------------------------------------------ - -SUBROUTINE shr_file_chdir(model, rcodeOut) - -! !USES: - - implicit none - -! !INPUT/OUTPUT PARAMETERS: - - character(*) ,intent(in) :: model ! used to construct env varible name - integer(SHR_KIND_IN),intent(out),optional :: rcodeOut ! Return error code - -!EOP - - !--- local --- - character(SHR_KIND_CL) :: dir ! directory to cd to - integer (SHR_KIND_IN) :: rcode ! Return error code - character(SHR_KIND_CL) :: filename ! namelist file to read - - !--- formats --- - character(*),parameter :: subName = '(shr_file_chdir) ' - character(*),parameter :: F00 = "('(shr_file_chdir) ',4a)" - -!------------------------------------------------------------------------------- -! Notes: -!------------------------------------------------------------------------------- - - call shr_file_stdioReadNL( model, filename, dirOut=dir, rcodeOut=rcode ) - if (dir /= "nochange") then - call shr_sys_chdir(dir ,rcode) - if (s_loglev > 0) write(s_logunit,F00) "read ",trim(filename),", changed cwd to ",trim(dir) - else - if (s_loglev > 0) write(s_logunit,F00) "read ",trim(filename),", cwd has *not* been changed" - rcode = 1 - endif - if ( present(rcodeOut) ) rcodeOut = rcode - -END SUBROUTINE shr_file_chdir - -!=============================================================================== -!BOP =========================================================================== -! -! !IROUTINE: shr_file_dirio --- Change stdin and stdout. -! -! !DESCRIPTION: -! change the stdin & stdout (units 5 & 6), see shr_file_stdio for notes -! -! !INTERFACE: ------------------------------------------------------------------ - -SUBROUTINE shr_file_dirio(model) - - implicit none - -! !INPUT/OUTPUT PARAMETERS: - - character(*),intent(in) :: model ! used to construct env varible name - -!EOP - - !--- local --- - - !--- formats --- - character(*),parameter :: subName = '(shr_file_dirio) ' - -!------------------------------------------------------------------------------- -! Notes: -! -!------------------------------------------------------------------------------- - - call shr_file_chStdIn (model) - call shr_file_chStdOut(model) - -END SUBROUTINE shr_file_dirio - -!=============================================================================== -!BOP =========================================================================== -! -! !IROUTINE: shr_file_chStdIn -- Change stdin -! -! !DESCRIPTION: -! change the stdin (unit 5), see shr_file_stdio for notes -! -! !INTERFACE: ------------------------------------------------------------------ - -SUBROUTINE shr_file_chStdIn( model, NLFilename, rcodeOut ) - - implicit none - -! !INPUT/OUTPUT PARAMETERS: - - character(*) ,intent(in) :: model ! used to construct env var name - character(SHR_KIND_CL),intent(out),optional :: NLFilename ! open unit 5 to this - integer (SHR_KIND_IN),intent(out),optional :: rcodeOut ! return code - -!EOP - - !--- local --- - character(SHR_KIND_CL) :: stdin ! open unit 5 to this file - character(SHR_KIND_CL) :: nlfile ! Namelist filename for model to read from - character(SHR_KIND_CL) :: filename ! namelist file to read - integer (SHR_KIND_IN) :: rcode ! return code - - !--- formats --- - character(*),parameter :: subName = '(shr_file_chStdIn) ' - character(*),parameter :: F00 = "('(shr_file_chStdIn) ',4a)" - -!------------------------------------------------------------------------------- -! Notes: -!------------------------------------------------------------------------------- - - call shr_file_stdioReadNL( model, filename, stdinOut=stdin, & - nlfileOut=nlfile, rcodeOut=rcode ) - if (stdin /= "nochange") then - open(unit=5,file=stdin ,status='UNKNOWN',iostat=rcode) - if ( rcode /= 0 )then - if (s_loglev > 0) & - write(s_logunit,F00) "read ",trim(filename),': error opening file as unit 5:', & - trim(nlfile) - else - if (s_loglev > 0) & - write(s_logunit,F00) "read ",trim(filename),': unit 5 connected to ', & - trim(stdin) - end if - else - if (s_loglev > 0) write(s_logunit,F00) "read ",trim(filename), & - ': unit 5 has *not* been redirected' - endif - if ( len_trim(nlfile) > 0) then - if (s_loglev > 0) write(s_logunit,F00) "read ",trim(filename), & - ': read namelist from file:',trim(nlfile) - if ( .not. present(NLFilename) )then - if (s_loglev > 0) write(s_logunit,F00) "error: namelist filename NOT present" - rcode = 7 - end if - else - if (s_loglev > 0) write(s_logunit,F00) "read ",trim(filename),", " - if ( present(NLFilename) )then - if (s_loglev > 0) write(s_logunit,F00) "error: namelist filename present, but null" - rcode = 8 - end if - endif - if ( present(NLFilename) ) NLFilename = nlfile - if ( present(rcodeOut) ) rcodeOut = rcode - -END SUBROUTINE shr_file_chStdIn - -!=============================================================================== -!BOP =========================================================================== -! -! !IROUTINE: shr_file_stdout -- Change stdout -! -! !DESCRIPTION: -! change the stdout (unit 6), see shr_file_stdio for notes -! -! !INTERFACE: ------------------------------------------------------------------ - -SUBROUTINE shr_file_chStdOut(model,rcodeOut) - - implicit none - -! !INPUT/OUTPUT PARAMETERS: - !--- arguments --- - character(*) ,intent(in) :: model ! used to construct env varible name - integer(SHR_KIND_IN),intent(out),optional :: rcodeOut ! Return error code -!EOP - - !--- local --- - character(SHR_KIND_CL) :: filename ! namelist file to read - character(SHR_KIND_CL) :: stdout ! open unit 6 to this file - integer (SHR_KIND_IN) :: rcode ! return code - - !--- formats --- - character(*),parameter :: subName = '(shr_file_chStdOut) ' - character(*),parameter :: F00 = "('(shr_file_chStdOut) ',4a)" - -!------------------------------------------------------------------------------- -! Notes: -!------------------------------------------------------------------------------- - - call shr_file_stdioReadNL( model, filename, stdoutOut=stdout, & - rcodeOut=rcode ) - if (stdout /= "nochange") then - close(6) - open(unit=6,file=stdout,position='APPEND') - if (s_loglev > 0) write(s_logunit,F00) "read ",trim(filename), & - ': unit 6 connected to ',trim(stdout) - call shr_sys_flush(s_logunit) - else - if (s_loglev > 0) write(s_logunit,F00) "read ",trim(filename), & - ': unit 6 has *not* been redirected' - rcode = 1 - endif - - if ( present(rcodeOut) ) rcodeOut = rcode - -END SUBROUTINE shr_file_chStdOut - -!=============================================================================== -!BOP =========================================================================== -! -! !IROUTINE: shr_file_stdioReadNL -- read in stdio namelist -! -! !DESCRIPTION: -! Read in the stdio namelist for any given model type. Return any of the -! needed input namelist variables as optional arguments. Return "nochange" in -! dir, stdin, or stdout if shouldn't change. -! -! !INTERFACE: ------------------------------------------------------------------ - -SUBROUTINE shr_file_stdioReadNL( model, filename, dirOut, stdinOut, stdoutOut, & - NLFileOut, rcodeOut ) - - implicit none - -! !INPUT/OUTPUT PARAMETERS: - - character(*) ,intent(in) :: model ! used to construct env varible name - character(SHR_KIND_CL),intent(out) :: filename ! nml file to read from unit 5 - character(SHR_KIND_CL),intent(out),optional :: NLFileOut ! open unit 6 to this file - character(SHR_KIND_CL),intent(out),optional :: dirOut ! directory to cd to - character(SHR_KIND_CL),intent(out),optional :: stdinOut ! open unit 5 to this file - character(SHR_KIND_CL),intent(out),optional :: stdoutOut ! open unit 6 to this file - integer (SHR_KIND_IN),intent(out),optional :: rcodeOut ! return code - -!EOP - - !--- local --- - logical :: exists ! true iff file exists - character(SHR_KIND_CL) :: dir ! directory to cd to - character(SHR_KIND_CL) :: stdin ! open unit 5 to this file - character(SHR_KIND_CL) :: stdout ! open unit 6 to this file - character(SHR_KIND_CL) :: NLFile ! namelist file to read seperately - integer (SHR_KIND_IN) :: rcode ! return code - integer (SHR_KIND_IN) :: unit ! Unit to read from - - namelist / stdio / dir,stdin,stdout,NLFile - - !--- formats --- - character(*),parameter :: subName = '(shr_file_stdioReadNL) ' - character(*),parameter :: F00 = "('(shr_file_stdioReadNL) ',4a)" - character(*),parameter :: F01 = "('(shr_file_stdioReadNL) ',2a,i6)" - -!------------------------------------------------------------------------------- -! Notes: -! -!------------------------------------------------------------------------------- - - rcode = 0 - dir = "nochange" - stdin = "nochange" - stdout = "nochange" - NLFile = " " - - filename = trim(model)//"_stdio.nml" ! eg. file="cpl_stdio.nml" - inquire(file=filename,exist=exists) - - if (.not. exists) then - if (s_loglev > 0) write(s_logunit,F00) "file ",trim(filename),& - & " doesn't exist, can not read stdio namelist from it" - rcode = 9 - else - unit = shr_file_getUnit() - open (unit,file=filename,action="READ") - read (unit,nml=stdio,iostat=rcode) - close(unit) - call shr_file_freeUnit( unit ) - if (rcode /= 0) then - write(s_logunit,F01) 'ERROR: reading ',trim(filename),': iostat=',rcode - call shr_sys_abort(subName//" ERROR reading "//trim(filename) ) - end if - endif - if ( len_trim(NLFile) > 0 .and. trim(stdin) /= "nochange" )then - write(s_logunit,F00) "Error: input namelist:" - write(s_logunit,nml=stdio) - call shr_sys_abort(subName//" ERROR trying to both redirect AND "// & - "open namelist filename" ) - end if - if ( present(NLFileOut) ) NLFileOut = NLFile - if ( present(dirOut) ) dirOut = dir - if ( present(stdinOut) ) stdinOut = stdin - if ( present(stdoutOut) ) stdoutOut = stdout - if ( present(rcodeOut) ) rcodeOut = rcode - -END SUBROUTINE shr_file_stdioReadNL - -!=============================================================================== -!BOP =========================================================================== -! -! !IROUTINE: shr_file_setIO -- read in stdio namelist -! -! !DESCRIPTION: -! This opens a namelist file specified as an argument and then opens -! a log file associated with the unit argument. This may be extended -! in the future. -! -! !INTERFACE: ------------------------------------------------------------------ - -SUBROUTINE shr_file_setIO( nmlfile, funit) - - implicit none - -! !INPUT/OUTPUT PARAMETERS: - - character(len=*) ,intent(in) :: nmlfile ! namelist filename - integer(SHR_KIND_IN),intent(in) :: funit ! unit number for log file - -!EOP - - !--- local --- - logical :: exists ! true if file exists - character(SHR_KIND_CL) :: diri ! directory to cd to - character(SHR_KIND_CL) :: diro ! directory to cd to - character(SHR_KIND_CL) :: logfile ! open unit 6 to this file - integer(SHR_KIND_IN) :: unit ! unit number - integer(SHR_KIND_IN) :: rcode ! error code - - namelist / modelio / diri,diro,logfile - - !--- formats --- - character(*),parameter :: subName = '(shr_file_setIO) ' - character(*),parameter :: F00 = "('(shr_file_setIO) ',4a)" - character(*),parameter :: F01 = "('(shr_file_setIO) ',2a,i6)" - -!------------------------------------------------------------------------------- -! Notes: -! -!------------------------------------------------------------------------------- - - diri = "." - diro = "." - logfile = "" - - inquire(file=nmlfile,exist=exists) - - if (.not. exists) then - if (s_loglev > 0) write(s_logunit,F00) "file ",trim(nmlfile)," non existant" - return - else - unit = shr_file_getUnit() - open (unit,file=nmlfile,action="READ") - read (unit,nml=modelio,iostat=rcode) - close(unit) - call shr_file_freeUnit( unit ) - if (rcode /= 0) then - write(s_logunit,F01) 'ERROR: reading ',trim(nmlfile),': iostat=',rcode - call shr_sys_abort(subName//" ERROR reading "//trim(nmlfile) ) - end if - endif - - if (len_trim(logfile) > 0) then - open(funit,file=trim(diro)//"/"//trim(logfile)) - else - if (s_loglev > 0) write(s_logunit,F00) "logfile not opened" - endif - -END SUBROUTINE shr_file_setIO - -!=============================================================================== -!BOP =========================================================================== -! -! !IROUTINE: shr_file_setLogUnit -- Set the Log I/O Unit number -! -! !INTERFACE: ------------------------------------------------------------------ - -SUBROUTINE shr_file_setLogUnit(unit) - - implicit none - -! !INPUT/OUTPUT PARAMETERS: - - integer(SHR_KIND_IN),intent(in) :: unit ! new unit number - -!EOP - - !--- formats --- - character(*),parameter :: subName = '(shr_file_setLogUnit) ' - character(*),parameter :: F00 = "('(shr_file_setLogUnit) ',4a)" - -!------------------------------------------------------------------------------- -! Notes: Caller must be sure it's a valid unit number -!------------------------------------------------------------------------------- - - if (s_loglev > 1 .and. s_logunit-unit /= 0) then - write(s_logunit,*) subName,': reset log unit number from/to ',s_logunit, unit - write( unit,*) subName,': reset log unit number from/to ',s_logunit, unit - endif - - s_logunit = unit - -END SUBROUTINE shr_file_setLogUnit - -!=============================================================================== -!BOP =========================================================================== -! -! !IROUTINE: shr_file_setLogLevel -- Set the Log I/O Unit number -! -! !INTERFACE: ------------------------------------------------------------------ - -SUBROUTINE shr_file_setLogLevel(newlevel) - - implicit none - -! !INPUT/OUTPUT PARAMETERS: - - integer(SHR_KIND_IN),intent(in) :: newlevel ! new log level - -!EOP - - !--- formats --- - character(*),parameter :: subName = '(shr_file_setLogLevel) ' - character(*),parameter :: F00 = "('(shr_file_setLogLevel) ',4a)" - -!------------------------------------------------------------------------------- -! Notes: -!------------------------------------------------------------------------------- - - if (s_loglev+newlevel > 2 .and. s_loglev-newlevel /= 0) & - write(s_logunit,*) subName,': reset log level from/to ',s_loglev, newlevel - - s_loglev = newlevel - -END SUBROUTINE shr_file_setLogLevel - -!=============================================================================== -!BOP =========================================================================== -! -! !IROUTINE: shr_file_getLogUnit -- Set the Log I/O Unit number -! -! !INTERFACE: ------------------------------------------------------------------ - -SUBROUTINE shr_file_getLogUnit(unit) - - implicit none - -! !INPUT/OUTPUT PARAMETERS: - - integer(SHR_KIND_IN),intent(out) :: unit ! new unit number - -!EOP - - !--- formats --- - character(*),parameter :: subName = '(shr_file_getLogUnit) ' - character(*),parameter :: F00 = "('(shr_file_getLogUnit) ',4a)" - -!------------------------------------------------------------------------------- -! Notes: -!------------------------------------------------------------------------------- - - unit = s_logunit - -END SUBROUTINE shr_file_getLogUnit - -!=============================================================================== -!BOP =========================================================================== -! -! !IROUTINE: shr_file_getLogLevel -- Set the Log I/O Unit number -! -! !INTERFACE: ------------------------------------------------------------------ - -SUBROUTINE shr_file_getLogLevel(curlevel) - - implicit none - -! !INPUT/OUTPUT PARAMETERS: - - integer(SHR_KIND_IN),intent(out) :: curlevel ! new log level - -!EOP - - !--- formats --- - character(*),parameter :: subName = '(shr_file_getLogLevel) ' - character(*),parameter :: F00 = "('(shr_file_getLogLevel) ',4a)" - -!------------------------------------------------------------------------------- -! Notes: -!------------------------------------------------------------------------------- - - curlevel = s_loglev - -END SUBROUTINE shr_file_getLogLevel - -!=============================================================================== -!=============================================================================== - -END MODULE shr_file_mod diff --git a/tools/mksurfdata_map/src/shr_log_mod.F90 b/tools/mksurfdata_map/src/shr_log_mod.F90 deleted file mode 100644 index 244314a8de..0000000000 --- a/tools/mksurfdata_map/src/shr_log_mod.F90 +++ /dev/null @@ -1,13 +0,0 @@ -MODULE shr_log_mod - - use shr_kind_mod - - !---------------------------------------------------------------------------- - ! low-level shared variables for logging, these may not be parameters - !---------------------------------------------------------------------------- - public - - integer(SHR_KIND_IN) :: shr_log_Level = 1 - integer(SHR_KIND_IN) :: shr_log_Unit = 6 - -END MODULE shr_log_mod diff --git a/tools/mksurfdata_map/src/shr_string_mod.F90 b/tools/mksurfdata_map/src/shr_string_mod.F90 deleted file mode 100644 index 44697ceaee..0000000000 --- a/tools/mksurfdata_map/src/shr_string_mod.F90 +++ /dev/null @@ -1,1753 +0,0 @@ -!=============================================================================== -!BOP =========================================================================== -! -! !MODULE: shr_string_mod -- string and list methods -! -! !DESCRIPTION: -! General string and specific list method. A list is a single string -! that is delimited by a character forming multiple fields, ie, -! character(len=*) :: mylist = "t:s:u1:v1:u2:v2:taux:tauy" -! The delimiter is called listDel in this module, is default ":", -! but can be set by a call to shr_string_listSetDel. -! -! !REVISION HISTORY: -! 2005-Apr-28 - T. Craig - first version -! -! !INTERFACE: ------------------------------------------------------------------ - -module shr_string_mod - -! !USES: - - use shr_kind_mod ! F90 kinds - use shr_sys_mod ! shared system calls - use shr_timer_mod, only : shr_timer_get, shr_timer_start, shr_timer_stop - use shr_log_mod, only : s_loglev => shr_log_Level - use shr_log_mod, only : s_logunit => shr_log_Unit - - implicit none - private - -! !PUBLIC TYPES: - - ! no public types - -! !PUBLIC MEMBER FUNCTIONS: - - public :: shr_string_countChar ! Count number of char in string, fn - public :: shr_string_toUpper ! Convert string to upper-case - public :: shr_string_toLower ! Convert string to lower-case - public :: shr_string_getParentDir ! For a pathname get the parent directory name - public :: shr_string_lastIndex ! Index of last substr in str - public :: shr_string_endIndex ! Index of end of substr in str - public :: shr_string_leftAlign ! remove leading white space - public :: shr_string_alphanum ! remove all non alpha-numeric characters - public :: shr_string_betweenTags ! get the substring between the two tags - public :: shr_string_parseCFtunit ! parse CF time units - public :: shr_string_clean ! Set string to all white space - - public :: shr_string_listIsValid ! test for a valid "list" - public :: shr_string_listGetNum ! Get number of fields in list, fn - public :: shr_string_listGetIndex ! Get index of field - public :: shr_string_listGetIndexF ! function version of listGetIndex - public :: shr_string_listGetName ! get k-th field name - public :: shr_string_listIntersect ! get intersection of two field lists - public :: shr_string_listUnion ! get union of two field lists - public :: shr_string_listMerge ! merge two lists to form third - public :: shr_string_listAppend ! append list at end of another - public :: shr_string_listPrepend ! prepend list in front of another - public :: shr_string_listSetDel ! Set field delimeter in lists - public :: shr_string_listGetDel ! Get field delimeter in lists - - public :: shr_string_setAbort ! set local abort flag - public :: shr_string_setDebug ! set local debug flag - -! !PUBLIC DATA MEMBERS: - - ! no public data members - -!EOP - - character(len=1) ,save :: listDel = ":" ! note single exec implications - character(len=2) ,save :: listDel2 = "::" ! note single exec implications - logical ,save :: doabort = .true. - integer(SHR_KIND_IN),save :: debug = 0 - -!=============================================================================== -contains -!=============================================================================== - -!=============================================================================== -!BOP =========================================================================== -! -! !IROUTINE: shr_string_countChar -- Count number of occurances of a character -! -! !DESCRIPTION: -! count number of occurances of a single character in a string -! \newline -! n = shr\_string\_countChar(string,character) -! -! !REVISION HISTORY: -! 2005-Feb-28 - First version from dshr_bundle -! -! !INTERFACE: ------------------------------------------------------------------ - -integer function shr_string_countChar(str,char,rc) - - - implicit none - -! !INPUT/OUTPUT PARAMETERS: - - character(*) ,intent(in) :: str ! string to search - character(1) ,intent(in) :: char ! char to search for - integer(SHR_KIND_IN),intent(out),optional :: rc ! return code - -!EOP - - !----- local ----- - integer(SHR_KIND_IN) :: count ! counts occurances of char - integer(SHR_KIND_IN) :: n ! generic index - integer(SHR_KIND_IN) :: t01 = 0 ! timer - - !----- formats ----- - character(*),parameter :: subName = "(shr_string_countChar) " - character(*),parameter :: F00 = "('(shr_string_countChar) ',4a)" - -!------------------------------------------------------------------------------- -! Notes: -!------------------------------------------------------------------------------- - - if (debug>1 .and. t01<1) call shr_timer_get(t01,subName) - if (debug>1) call shr_timer_start(t01) - - count = 0 - do n = 1, len_trim(str) - if (str(n:n) == char) count = count + 1 - end do - shr_string_countChar = count - - if (present(rc)) rc = 0 - - if (debug>1) call shr_timer_stop (t01) - -end function shr_string_countChar - -!=============================================================================== -!BOP =========================================================================== -! !IROUTINE: shr_string_toUpper -- Convert string to upper case -! -! !DESCRIPTION: -! Convert the input string to upper-case. -! Use achar and iachar intrinsics to ensure use of ascii collating sequence. -! -! !REVISION HISTORY: -! 2005-Dec-20 - Move CAM version over to shared code. -! -! !INTERFACE: ------------------------------------------------------------------ - -function shr_string_toUpper(str) - - implicit none - -! !INPUT/OUTPUT PARAMETERS: - character(len=*), intent(in) :: str ! String to convert to upper case - character(len=len(str)) :: shr_string_toUpper - - !----- local ----- - integer(SHR_KIND_IN) :: i ! Index - integer(SHR_KIND_IN) :: aseq ! ascii collating sequence - integer(SHR_KIND_IN) :: LowerToUpper ! integer to convert case - character(len=1) :: ctmp ! Character temporary - integer(SHR_KIND_IN) :: t01 = 0 ! timer - - !----- formats ----- - character(*),parameter :: subName = "(shr_string_toUpper) " - character(*),parameter :: F00 = "('(shr_string_toUpper) ',4a)" - -!------------------------------------------------------------------------------- -! -!------------------------------------------------------------------------------- - - if (debug>1 .and. t01<1) call shr_timer_get(t01,subName) - if (debug>1) call shr_timer_start(t01) - - LowerToUpper = iachar("A") - iachar("a") - - do i = 1, len(str) - ctmp = str(i:i) - aseq = iachar(ctmp) - if ( aseq >= iachar("a") .and. aseq <= iachar("z") ) & - ctmp = achar(aseq + LowertoUpper) - shr_string_toUpper(i:i) = ctmp - end do - - if (debug>1) call shr_timer_stop (t01) - -end function shr_string_toUpper - -!=============================================================================== -!BOP =========================================================================== -! !IROUTINE: shr_string_toLower -- Convert string to lower case -! -! !DESCRIPTION: -! Convert the input string to lower-case. -! Use achar and iachar intrinsics to ensure use of ascii collating sequence. -! -! !REVISION HISTORY: -! 2006-Apr-20 - Creation -! -! !INTERFACE: ------------------------------------------------------------------ -function shr_string_toLower(str) - - implicit none - -! !INPUT/OUTPUT PARAMETERS: - character(len=*), intent(in) :: str ! String to convert to lower case - character(len=len(str)) :: shr_string_toLower - - !----- local ----- - integer(SHR_KIND_IN) :: i ! Index - integer(SHR_KIND_IN) :: aseq ! ascii collating sequence - integer(SHR_KIND_IN) :: UpperToLower ! integer to convert case - character(len=1) :: ctmp ! Character temporary - integer(SHR_KIND_IN) :: t01 = 0 ! timer - - !----- formats ----- - character(*),parameter :: subName = "(shr_string_toLower) " - character(*),parameter :: F00 = "('(shr_string_toLower) ',4a)" - -!------------------------------------------------------------------------------- -! -!------------------------------------------------------------------------------- - - if (debug>1 .and. t01<1) call shr_timer_get(t01,subName) - if (debug>1) call shr_timer_start(t01) - - UpperToLower = iachar("a") - iachar("A") - - do i = 1, len(str) - ctmp = str(i:i) - aseq = iachar(ctmp) - if ( aseq >= iachar("A") .and. aseq <= iachar("Z") ) & - ctmp = achar(aseq + UpperToLower) - shr_string_toLower(i:i) = ctmp - end do - - if (debug>1) call shr_timer_stop (t01) - -end function shr_string_toLower - -!=============================================================================== -!BOP =========================================================================== -! !IROUTINE: shr_string_getParentDir -- For pathname get the parent directory name -! -! !DESCRIPTION: -! Get the parent directory name for a pathname. -! -! !REVISION HISTORY: -! 2006-May-09 - Creation -! -! !INTERFACE: ------------------------------------------------------------------ - -function shr_string_getParentDir(str) - - implicit none - -! !INPUT/OUTPUT PARAMETERS: - character(len=*), intent(in) :: str ! String to convert to lower case - character(len=len(str)) :: shr_string_getParentDir - - !----- local ----- - integer(SHR_KIND_IN) :: i ! Index - integer(SHR_KIND_IN) :: nlen ! Length of string - integer(SHR_KIND_IN) :: t01 = 0 ! timer - - !----- formats ----- - character(*),parameter :: subName = "(shr_string_getParentDir) " - character(*),parameter :: F00 = "('(shr_string_getParentDir) ',4a)" - -!------------------------------------------------------------------------------- -! -!------------------------------------------------------------------------------- - - if (debug>1 .and. t01<1) call shr_timer_get(t01,subName) - if (debug>1) call shr_timer_start(t01) - - nlen = len_trim(str) - if ( str(nlen:nlen) == "/" ) nlen = nlen - 1 - i = index( str(1:nlen), "/", back=.true. ) - if ( i == 0 )then - shr_string_getParentDir = str - else - shr_string_getParentDir = str(1:i-1) - end if - - if (debug>1) call shr_timer_stop (t01) - -end function shr_string_getParentDir - -!=============================================================================== -!BOP =========================================================================== -! -! -! !IROUTINE: shr_string_lastIndex -- Get index of last substr within string -! -! !DESCRIPTION: -! Get index of last substr within string -! \newline -! n = shr\_string\_lastIndex(string,substring) -! -! !REVISION HISTORY: -! 2005-Feb-28 - First version from dshr_domain -! -! !INTERFACE: ------------------------------------------------------------------ - -integer function shr_string_lastIndex(string,substr,rc) - - implicit none - -! !INPUT/OUTPUT PARAMETERS: - - character(*) ,intent(in) :: string ! string to search - character(*) ,intent(in) :: substr ! sub-string to search for - integer(SHR_KIND_IN),intent(out),optional :: rc ! return code - -!EOP - - !--- local --- - integer(SHR_KIND_IN) :: t01 = 0 ! timer - - !----- formats ----- - character(*),parameter :: subName = "(shr_string_lastIndex) " - character(*),parameter :: F00 = "('(shr_string_lastIndex) ',4a)" - -!------------------------------------------------------------------------------- -! Note: -! - "new" F90 back option to index function makes this home-grown solution obsolete -!------------------------------------------------------------------------------- - - if (debug>1 .and. t01<1) call shr_timer_get(t01,subName) - if (debug>1) call shr_timer_start(t01) - - shr_string_lastIndex = index(string,substr,.true.) - - if (present(rc)) rc = 0 - - if (debug>1) call shr_timer_stop (t01) - -end function shr_string_lastIndex - -!=============================================================================== -!BOP =========================================================================== -! -! !IROUTINE: shr_string_endIndex -- Get the ending index of substr within string -! -! !DESCRIPTION: -! Get the ending index of substr within string -! \newline -! n = shr\_string\_endIndex(string,substring) -! -! !REVISION HISTORY: -! 2005-May-10 - B. Kauffman, first version. -! -! !INTERFACE: ------------------------------------------------------------------ - -integer function shr_string_endIndex(string,substr,rc) - - implicit none - -! !INPUT/OUTPUT PARAMETERS: - - character(*) ,intent(in) :: string ! string to search - character(*) ,intent(in) :: substr ! sub-string to search for - integer(SHR_KIND_IN),intent(out),optional :: rc ! return code - -!EOP - - !--- local --- - integer(SHR_KIND_IN) :: i ! generic index - integer(SHR_KIND_IN) :: t01 = 0 ! timer - - !----- formats ----- - character(*),parameter :: subName = "(shr_string_endIndex) " - character(*),parameter :: F00 = "('(shr_string_endIndex) ',4a)" - -!------------------------------------------------------------------------------- -! Notes: -! * returns zero if substring not found, uses len_trim() intrinsic -! * very similar to: i = index(str,substr,back=.true.) -! * do we need this function? -!------------------------------------------------------------------------------- - - if (debug>1 .and. t01<1) call shr_timer_get(t01,subName) - if (debug>1) call shr_timer_start(t01) - - i = index(trim(string),trim(substr)) - if ( i == 0 ) then - shr_string_endIndex = 0 ! substr is not in string - else - shr_string_endIndex = i + len_trim(substr) - 1 - end if - -! ------------------------------------------------------------------- -! i = index(trim(string),trim(substr),back=.true.) -! if (i == len(string)+1) i = 0 -! shr_string_endIndex = i -! ------------------------------------------------------------------- - - if (present(rc)) rc = 0 - - if (debug>1) call shr_timer_stop (t01) - -end function shr_string_endIndex - -!=============================================================================== -!BOP =========================================================================== -! -! !IROUTINE: shr_string_leftAlign -- remove leading white space -! -! !DESCRIPTION: -! Remove leading white space -! \newline -! call shr\_string\_leftAlign(string) -! -! !REVISION HISTORY: -! 2005-Apr-28 - B. Kauffman - First version -! -! !INTERFACE: ------------------------------------------------------------------ - -subroutine shr_string_leftAlign(str,rc) - - implicit none - -! !INPUT/OUTPUT PARAMETERS: - - character(*) ,intent(inout) :: str - integer(SHR_KIND_IN),intent(out) ,optional :: rc ! return code - -!EOP - - !----- local ---- - integer(SHR_KIND_IN) :: rCode ! return code - integer(SHR_KIND_IN) :: t01 = 0 ! timer - - !----- formats ----- - character(*),parameter :: subName = "(shr_string_leftAlign) " - character(*),parameter :: F00 = "('(shr_string_leftAlign) ',4a)" - -!------------------------------------------------------------------------------- -! note: -! * ?? this routine isn't needed, use the intrisic adjustL instead ?? -!------------------------------------------------------------------------------- - - if (debug>1 .and. t01<1) call shr_timer_get(t01,subName) - if (debug>1) call shr_timer_start(t01) - -! ------------------------------------------------------------------- -! --- I used this until I discovered the intrinsic function below - BK -! do while (len_trim(str) > 0 ) -! if (str(1:1) /= ' ') exit -! str = str(2:len_trim(str)) -! end do -! rCode = 0 -! !! (len_trim(str) == 0 ) rCode = 1 ! ?? appropriate ?? -! ------------------------------------------------------------------- - - str = adjustL(str) - if (present(rc)) rc = 0 - - if (debug>1) call shr_timer_stop (t01) - -end subroutine shr_string_leftAlign - -!=============================================================================== -!BOP =========================================================================== -! -! !IROUTINE: shr_string_alphanum -- remove non alpha numeric characters -! -! !DESCRIPTION: -! Remove all non alpha numeric characters from string -! \newline -! call shr\_string\_alphanum(string) -! -! !REVISION HISTORY: -! 2005-Aug-01 - T. Craig - First version -! -! !INTERFACE: ------------------------------------------------------------------ - -subroutine shr_string_alphanum(str,rc) - - implicit none - -! !INPUT/OUTPUT PARAMETERS: - - character(*) ,intent(inout) :: str - integer(SHR_KIND_IN),intent(out) ,optional :: rc ! return code - -!EOP - - !----- local ---- - integer(SHR_KIND_IN) :: rCode ! return code - integer(SHR_KIND_IN) :: n,icnt ! counters - integer(SHR_KIND_IN) :: t01 = 0 ! timer - - !----- formats ----- - character(*),parameter :: subName = "(shr_string_alphaNum) " - character(*),parameter :: F00 = "('(shr_string_alphaNum) ',4a)" - -!------------------------------------------------------------------------------- -! -!------------------------------------------------------------------------------- - - if (debug>1 .and. t01<1) call shr_timer_get(t01,subName) - if (debug>1) call shr_timer_start(t01) - - icnt = 0 - do n=1,len_trim(str) - if ((str(n:n) >= 'a' .and. str(n:n) <= 'z') .or. & - (str(n:n) >= 'A' .and. str(n:n) <= 'Z') .or. & - (str(n:n) >= '0' .and. str(n:n) <= '9')) then - icnt = icnt + 1 - str(icnt:icnt) = str(n:n) - endif - enddo - do n=icnt+1,len(str) - str(n:n) = ' ' - enddo - - if (present(rc)) rc = 0 - - if (debug>1) call shr_timer_stop (t01) - -end subroutine shr_string_alphanum - -!=============================================================================== -!BOP =========================================================================== -! -! !IROUTINE: shr_string_betweenTags -- Get the substring between the two tags. -! -! !DESCRIPTION: -! Get the substring found between the start and end tags. -! \newline -! call shr\_string\_betweenTags(string,startTag,endTag,substring,rc) -! -! !REVISION HISTORY: -! 2005-May-11 - B. Kauffman, first version -! -! !INTERFACE: ------------------------------------------------------------------ - -subroutine shr_string_betweenTags(string,startTag,endTag,substr,rc) - - implicit none - -! !INPUT/OUTPUT PARAMETERS: - - character(*) ,intent(in) :: string ! string to search - character(*) ,intent(in) :: startTag ! start tag - character(*) ,intent(in) :: endTag ! end tag - character(*) ,intent(out) :: substr ! sub-string between tags - integer(SHR_KIND_IN),intent(out),optional :: rc ! retrun code - -!EOP - - !--- local --- - integer(SHR_KIND_IN) :: iStart ! substring start index - integer(SHR_KIND_IN) :: iEnd ! substring end index - integer(SHR_KIND_IN) :: rCode ! return code - integer(SHR_KIND_IN) :: t01 = 0 ! timer - - !----- formats ----- - character(*),parameter :: subName = "(shr_string_betweenTags) " - character(*),parameter :: F00 = "('(shr_string_betweenTags) ',4a)" - -!------------------------------------------------------------------------------- -! Notes: -! * assumes the leading/trailing white space is not part of start & end tags -!------------------------------------------------------------------------------- - - if (debug>1 .and. t01<1) call shr_timer_get(t01,subName) - if (debug>1) call shr_timer_start(t01) - - iStart = shr_string_endIndex(string,trim(adjustL(startTag))) ! end of start tag - iEnd = index(string,trim(adjustL(endTag ))) ! start of end tag - - rCode = 0 - substr = "" - - if (iStart < 1) then - if (s_loglev > 0) then - write(s_logunit,F00) "ERROR: can't find start tag in string" - write(s_logunit,F00) "ERROR: start tag = ",trim(startTag) - write(s_logunit,F00) "ERROR: string = ",trim(string) - endif - rCode = 1 - else if (iEnd < 1) then - if (s_loglev > 0) then - write(s_logunit,F00) "ERROR: can't find end tag in string" - write(s_logunit,F00) "ERROR: end tag = ",trim( endTag) - write(s_logunit,F00) "ERROR: string = ",trim(string) - endif - rCode = 2 - else if ( iEnd <= iStart) then - if (s_loglev > 0) then - write(s_logunit,F00) "ERROR: start tag not before end tag" - write(s_logunit,F00) "ERROR: start tag = ",trim(startTag) - write(s_logunit,F00) "ERROR: end tag = ",trim( endTag) - write(s_logunit,F00) "ERROR: string = ",trim(string) - endif - rCode = 3 - else if ( iStart+1 == iEnd ) then - substr = "" - if (s_loglev > 0) write(s_logunit,F00) "WARNING: zero-length substring found in ",trim(string) - else - substr = string(iStart+1:iEnd-1) - if (len_trim(substr) == 0 .and. s_loglev > 0) & - & write(s_logunit,F00) "WARNING: white-space substring found in ",trim(string) - end if - - if (present(rc)) rc = rCode - - if (debug>1) call shr_timer_stop (t01) - -end subroutine shr_string_betweenTags - -!=============================================================================== -!BOP =========================================================================== -! -! !IROUTINE: shr_string_parseCFtunit -- Parse CF time unit -! -! !DESCRIPTION: -! Parse CF time unit into a delta string name and a base time in yyyymmdd -! and seconds (nearest integer actually). -! \newline -! call shr\_string\_parseCFtunit(string,substring) -! \newline -! Input string is like "days since 0001-06-15 15:20:45.5 -6:00" -! - recognizes "days", "hours", "minutes", "seconds" -! - must have at least yyyy-mm-dd, hh:mm:ss.s is optional -! - expects a "since" in the string -! - ignores time zone part -! -! !REVISION HISTORY: -! 2005-May-15 - T. Craig - first version -! -! !INTERFACE: ------------------------------------------------------------------ - -subroutine shr_string_parseCFtunit(string,unit,bdate,bsec,rc) - - implicit none - -! !INPUT/OUTPUT PARAMETERS: - - character(*) ,intent(in) :: string ! string to search - character(*) ,intent(out) :: unit ! delta time unit - integer(SHR_KIND_IN),intent(out) :: bdate ! base date yyyymmdd - real(SHR_KIND_R8) ,intent(out) :: bsec ! base seconds - integer(SHR_KIND_IN),intent(out),optional :: rc ! return code - -!EOP - - !--- local --- - integer(SHR_KIND_IN) :: i,i1,i2 ! generic index - character(SHR_KIND_CL) :: tbase ! baseline time - character(SHR_KIND_CL) :: lstr ! local string - integer(SHR_KIND_IN) :: yr,mo,da,hr,min ! time stuff - real(SHR_KIND_R8) :: sec ! time stuff - integer(SHR_KIND_IN) :: t01 = 0 ! timer - - !----- formats ----- - character(*),parameter :: subName = "(shr_string_parseCFtunit) " - character(*),parameter :: F00 = "('(shr_string_parseCFtunit) ',4a)" - -!------------------------------------------------------------------------------- -! Notes: -! o assume length of CF-1.0 time attribute char string < SHR_KIND_CL -! This is a reasonable assumption. -!------------------------------------------------------------------------------- - - if (debug>1 .and. t01<1) call shr_timer_get(t01,subName) - if (debug>1) call shr_timer_start(t01) - - unit = 'none' - bdate = 0 - bsec = 0.0_SHR_KIND_R8 - - i = shr_string_lastIndex(string,'days ') - if (i > 0) unit = 'days' - i = shr_string_lastIndex(string,'hours ') - if (i > 0) unit = 'hours' - i = shr_string_lastIndex(string,'minutes ') - if (i > 0) unit = 'minutes' - i = shr_string_lastIndex(string,'seconds ') - if (i > 0) unit = 'seconds' - - if (trim(unit) == 'none') then - write(s_logunit,F00) ' ERROR time unit unknown' - call shr_string_abort(subName//' time unit unknown') - endif - - i = shr_string_lastIndex(string,' since ') - if (i < 1) then - write(s_logunit,F00) ' ERROR since does not appear in unit attribute for time ' - call shr_string_abort(subName//' no since in attr name') - endif - tbase = trim(string(i+6:)) - call shr_string_leftAlign(tbase) - - if (debug > 0 .and. s_logunit > 0) then - write(s_logunit,*) trim(subName)//' '//'unit '//trim(unit) - write(s_logunit,*) trim(subName)//' '//'tbase '//trim(tbase) - endif - - yr=0; mo=0; da=0; hr=0; min=0; sec=0 - i1 = 1 - - i2 = index(tbase,'-') - 1 - lstr = tbase(i1:i2) - read(lstr,*,ERR=200,END=200) yr - tbase = tbase(i2+2:) - call shr_string_leftAlign(tbase) - - i2 = index(tbase,'-') - 1 - lstr = tbase(i1:i2) - read(lstr,*,ERR=200,END=200) mo - tbase = tbase(i2+2:) - call shr_string_leftAlign(tbase) - - i2 = index(tbase,' ') - 1 - lstr = tbase(i1:i2) - read(lstr,*,ERR=200,END=200) da - tbase = tbase(i2+2:) - call shr_string_leftAlign(tbase) - - i2 = index(tbase,':') - 1 - lstr = tbase(i1:i2) - read(lstr,*,ERR=200,END=100) hr - tbase = tbase(i2+2:) - call shr_string_leftAlign(tbase) - - i2 = index(tbase,':') - 1 - lstr = tbase(i1:i2) - read(lstr,*,ERR=200,END=100) min - tbase = tbase(i2+2:) - call shr_string_leftAlign(tbase) - - i2 = index(tbase,' ') - 1 - lstr = tbase(i1:i2) - read(lstr,*,ERR=200,END=100) sec - -100 continue - - if (debug > 0 .and. s_loglev > 0) write(s_logunit,*) trim(subName),'ymdhms:',yr,mo,da,hr,min,sec - - bdate = abs(yr)*10000 + mo*100 + da - if (yr < 0) bdate = -bdate - bsec = real(hr*3600 + min*60,SHR_KIND_R8) + sec - - if (present(rc)) rc = 0 - - if (debug>1) call shr_timer_stop (t01) - return - -200 continue - write(s_logunit,F00) 'ERROR 200 on char num read ' - call shr_string_abort(subName//' ERROR on char num read') - if (debug>1) call shr_timer_stop (t01) - return - -end subroutine shr_string_parseCFtunit - -!=============================================================================== -!BOP =========================================================================== -! -! !IROUTINE: shr_string_clean -- Clean a string, set it to "blank" -! -! !DESCRIPTION: -! Clean a string, set it to blank -! \newline -! call shr\_string\_clean(string,rc) -! -! !REVISION HISTORY: -! 2005-May-05 - T. Craig -! -! !INTERFACE: ------------------------------------------------------------------ - -subroutine shr_string_clean(string,rc) - - implicit none - -! !INPUT/OUTPUT PARAMETERS: - - character(*) ,intent(inout) :: string ! list/string - integer(SHR_KIND_IN),optional,intent(out) :: rc ! return code - -!EOP - - !----- local ----- - integer(SHR_KIND_IN) :: n ! counter - integer(SHR_KIND_IN) :: rCode ! return code - integer(SHR_KIND_IN) :: t01 = 0 ! timer - - !----- formats ----- - character(*),parameter :: subName = "(shr_string_clean) " - character(*),parameter :: F00 = "('(shr_string_clean) ',4a)" - -!------------------------------------------------------------------------------- -! Notes: -!------------------------------------------------------------------------------- - - if (debug>1 .and. t01<1) call shr_timer_get(t01,subName) - if (debug>1) call shr_timer_start(t01) - - rCode = 0 - string = ' ' - if (present(rc)) rc = rCode - if (debug>1) call shr_timer_stop (t01) - -end subroutine shr_string_clean - -!=============================================================================== -!BOP =========================================================================== -! -! !IROUTINE: shr_string_listIsValid -- determine whether string is a valid list -! -! !DESCRIPTION: -! Determine whether string is a valid list -! \newline -! logical_var = shr\_string\_listIsValid(list,rc) -! -! !REVISION HISTORY: -! 2005-May-05 - B. Kauffman -! -! !INTERFACE: ------------------------------------------------------------------ - -logical function shr_string_listIsValid(list,rc) - - implicit none - -! !INPUT/OUTPUT PARAMETERS: - - character(*) ,intent(in) :: list ! list/string - integer(SHR_KIND_IN),optional,intent(out) :: rc ! return code - -!EOP - - !----- local ----- - integer (SHR_KIND_IN) :: nChar ! lenth of list - integer (SHR_KIND_IN) :: rCode ! return code - integer (SHR_KIND_IN) :: t01 = 0 ! timer - - !----- formats ----- - character(*),parameter :: subName = "(shr_string_listIsValid) " - character(*),parameter :: F00 = "('(shr_string_listIsValid) ',4a)" - -!------------------------------------------------------------------------------- -! check that the list conforms to the list format -!------------------------------------------------------------------------------- - - if (debug>1 .and. t01<1) call shr_timer_get(t01,subName) - if (debug>1) call shr_timer_start(t01) - - rCode = 0 - shr_string_listIsValid = .true. - - nChar = len_trim(list) - if (nChar < 1) then ! list is an empty string - rCode = 1 - else if ( list(1:1) == listDel ) then ! first char is delimiter - rCode = 2 - else if (list(nChar:nChar) == listDel ) then ! last char is delimiter - rCode = 3 - else if (index(trim(list)," " ) > 0) then ! white-space in a field name - rCode = 4 - else if (index(trim(list),listDel2) > 0) then ! found zero length field - rCode = 5 - end if - - if (rCode /= 0) then - shr_string_listIsValid = .false. - if (s_loglev > 0) write(s_logunit,F00) "WARNING: invalid list = ",trim(list) - endif - - if (present(rc)) rc = rCode - if (debug>1) call shr_timer_stop (t01) - -end function shr_string_listIsValid - -!=============================================================================== -!BOP =========================================================================== -! -! !IROUTINE: shr_string_listGetName -- Get name of k-th field in list -! -! !DESCRIPTION: -! Get name of k-th field in list -! \newline -! call shr\_string\_listGetName(list,k,name,rc) -! -! !REVISION HISTORY: -! 2005-May-05 - B. Kauffman -! -! !INTERFACE: ------------------------------------------------------------------ - -subroutine shr_string_listGetName(list,k,name,rc) - - implicit none - -! !INPUT/OUTPUT PARAMETERS: - - character(*) ,intent(in) :: list ! list/string - integer(SHR_KIND_IN) ,intent(in) :: k ! index of field - character(*) ,intent(out) :: name ! k-th name in list - integer(SHR_KIND_IN),optional,intent(out) :: rc ! return code - -!EOP - - !----- local ----- - integer(SHR_KIND_IN) :: i,j,n ! generic indecies - integer(SHR_KIND_IN) :: kFlds ! number of fields in list - integer(SHR_KIND_IN) :: i0,i1 ! name = list(i0:i1) - integer(SHR_KIND_IN) :: rCode ! return code - integer(SHR_KIND_IN) :: t01 = 0 ! timer - - !----- formats ----- - character(*),parameter :: subName = "(shr_string_listGetName) " - character(*),parameter :: F00 = "('(shr_string_listGetName) ',4a)" - -!------------------------------------------------------------------------------- -! Notes: -!------------------------------------------------------------------------------- - - if (debug>1 .and. t01<1) call shr_timer_get(t01,subName) - if (debug>1) call shr_timer_start(t01) - - rCode = 0 - - !--- check that this is a valid list --- - if (.not. shr_string_listIsValid(list,rCode) ) then - write(s_logunit,F00) "ERROR: invalid list = ",trim(list) - call shr_string_abort(subName//" ERROR: invalid list = "//trim(list)) - end if - - !--- check that this is a valid index --- - kFlds = shr_string_listGetNum(list) - if (k<1 .or. kFlds1) call shr_timer_stop (t01) - -end subroutine shr_string_listGetName - -!=============================================================================== -!BOP =========================================================================== -! -! !IROUTINE: shr_string_listIntersect -- Get intersection of two field lists -! -! !DESCRIPTION: -! Get intersection of two fields lists, write into third list -! \newline -! call shr\_string\_listIntersect(list1,list2,listout) -! -! !REVISION HISTORY: -! 2005-May-05 - T. Craig -! -! !INTERFACE: ------------------------------------------------------------------ - -subroutine shr_string_listIntersect(list1,list2,listout,rc) - - implicit none - -! !INPUT/OUTPUT PARAMETERS: - - character(*) ,intent(in) :: list1 ! list/string - character(*) ,intent(in) :: list2 ! list/string - character(*) ,intent(out) :: listout ! list/string - integer(SHR_KIND_IN),optional,intent(out) :: rc ! return code - -!EOP - - !----- local ----- - integer(SHR_KIND_IN) :: nf,n1,n2 ! counters - character(SHR_KIND_CS) :: name ! field name - integer(SHR_KIND_IN) :: rCode ! return code - integer(SHR_KIND_IN) :: t01 = 0 ! timer - - !----- formats ----- - character(*),parameter :: subName = "(shr_string_listIntersect) " - character(*),parameter :: F00 = "('(shr_string_listIntersect) ',4a)" - -!------------------------------------------------------------------------------- -! Notes: -!------------------------------------------------------------------------------- - - if (debug>1 .and. t01<1) call shr_timer_get(t01,subName) - if (debug>1) call shr_timer_start(t01) - - rCode = 0 - - nf = shr_string_listGetNum(list1) - call shr_string_clean(listout) - do n1 = 1,nf - call shr_string_listGetName(list1,n1,name,rCode) - n2 = shr_string_listGetIndexF(list2,name) - if (n2 > 0) then - call shr_string_listAppend(listout,name) - endif - enddo - - if (present(rc)) rc = rCode - if (debug>1) call shr_timer_stop (t01) - -end subroutine shr_string_listIntersect - -!=============================================================================== -!BOP =========================================================================== -! -! !IROUTINE: shr_string_listUnion -- Get union of two field lists -! -! !DESCRIPTION: -! Get union of two fields lists, write into third list -! \newline -! call shr\_string\_listUnion(list1,list2,listout) -! -! !REVISION HISTORY: -! 2005-May-05 - T. Craig -! -! !INTERFACE: ------------------------------------------------------------------ - -subroutine shr_string_listUnion(list1,list2,listout,rc) - - implicit none - -! !INPUT/OUTPUT PARAMETERS: - - character(*) ,intent(in) :: list1 ! list/string - character(*) ,intent(in) :: list2 ! list/string - character(*) ,intent(out) :: listout ! list/string - integer(SHR_KIND_IN),optional,intent(out) :: rc ! return code - -!EOP - - !----- local ----- - integer(SHR_KIND_IN) :: nf,n1,n2 ! counters - character(SHR_KIND_CS) :: name ! field name - integer(SHR_KIND_IN) :: rCode ! return code - integer(SHR_KIND_IN) :: t01 = 0 ! timer - - !----- formats ----- - character(*),parameter :: subName = "(shr_string_listUnion) " - character(*),parameter :: F00 = "('(shr_string_listUnion) ',4a)" - -!------------------------------------------------------------------------------- -! Notes: -!------------------------------------------------------------------------------- - - if (debug>1 .and. t01<1) call shr_timer_get(t01,subName) - if (debug>1) call shr_timer_start(t01) - rCode = 0 - - call shr_string_clean(listout) - - nf = shr_string_listGetNum(list1) - do n1 = 1,nf - call shr_string_listGetName(list1,n1,name,rCode) - n2 = shr_string_listGetIndexF(listout,name) - if (n2 < 1) then - call shr_string_listAppend(listout,name) - endif - enddo - - nf = shr_string_listGetNum(list2) - do n1 = 1,nf - call shr_string_listGetName(list2,n1,name,rCode) - n2 = shr_string_listGetIndexF(listout,name) - if (n2 < 1) then - call shr_string_listAppend(listout,name) - endif - enddo - - if (present(rc)) rc = rCode - if (debug>1) call shr_timer_stop (t01) - -end subroutine shr_string_listUnion - -!=============================================================================== -!BOP =========================================================================== -! -! !IROUTINE: shr_string_listMerge -- Merge lists two list to third -! -! !DESCRIPTION: -! Merge two list to third -! \newline -! call shr\_string\_listMerge(list1,list2,listout) -! call shr\_string\_listMerge(list1,list2,list1) -! -! !REVISION HISTORY: -! 2005-May-05 - T. Craig -! -! !INTERFACE: ------------------------------------------------------------------ - -subroutine shr_string_listMerge(list1,list2,listout,rc) - - implicit none -! !INPUT/OUTPUT PARAMETERS: - - character(*) ,intent(in) :: list1 ! list/string - character(*) ,intent(in) :: list2 ! list/string - character(*) ,intent(out) :: listout ! list/string - integer(SHR_KIND_IN),optional,intent(out) :: rc ! return code - -!EOP - - !----- local ----- - character(SHR_KIND_CX) :: l1,l2 ! local char strings - integer(SHR_KIND_IN) :: rCode ! return code - integer(SHR_KIND_IN) :: t01 = 0 ! timer - - !----- formats ----- - character(*),parameter :: subName = "(shr_string_listMerge) " - character(*),parameter :: F00 = "('(shr_string_listMerge) ',4a)" - -!------------------------------------------------------------------------------- -! Notes: -! - no input or output string should be longer than SHR_KIND_CX -!------------------------------------------------------------------------------- - - if (debug>1 .and. t01<1) call shr_timer_get(t01,subName) - if (debug>1) call shr_timer_start(t01) - rCode = 0 - - !--- make sure temp strings are large enough --- - if ( (len(l1) < len_trim(list1)) .or. (len(l2) < len_trim(list2))) then - call shr_string_abort(subName//'ERROR: temp string not large enough') - end if - - call shr_string_clean(l1) - call shr_string_clean(l2) - call shr_string_clean(listout) - l1 = trim(list1) - l2 = trim(list2) - call shr_string_leftAlign(l1,rCode) - call shr_string_leftAlign(l2,rCode) - if (len_trim(l1)+len_trim(l2)+1 > len(listout)) & - call shr_string_abort(subName//'ERROR: output list string not large enough') - if (len_trim(l1) == 0) then - listout = trim(l2) - else - listout = trim(l1)//":"//trim(l2) - endif - - if (present(rc)) rc = rCode - if (debug>1) call shr_timer_stop (t01) - -end subroutine shr_string_listMerge - -!=============================================================================== -!BOP =========================================================================== -! -! !IROUTINE: shr_string_listAppend -- Append one list to another -! -! !DESCRIPTION: -! Append one list to another -! \newline -! call shr\_string\_listAppend(list,listadd) -! -! !REVISION HISTORY: -! 2005-May-05 - T. Craig -! -! !INTERFACE: ------------------------------------------------------------------ - -subroutine shr_string_listAppend(list,listadd,rc) - - implicit none - -! !INPUT/OUTPUT PARAMETERS: - - character(*) ,intent(inout) :: list ! list/string - character(*) ,intent(in) :: listadd ! list/string - integer(SHR_KIND_IN),optional,intent(out) :: rc ! return code - -!EOP - - !----- local ----- - character(SHR_KIND_CX) :: l1 ! local string - integer(SHR_KIND_IN) :: rCode ! return code - integer(SHR_KIND_IN) :: t01 = 0 ! timer - - !----- formats ----- - character(*),parameter :: subName = "(shr_string_listAppend) " - character(*),parameter :: F00 = "('(shr_string_listAppend) ',4a)" - -!------------------------------------------------------------------------------- -! Notes: -! - no input or output string should be longer than SHR_KIND_CX -!------------------------------------------------------------------------------- - - if (debug>1 .and. t01<1) call shr_timer_get(t01,subName) - if (debug>1) call shr_timer_start(t01) - rCode = 0 - - !--- make sure temp string is large enough --- - if (len(l1) < len_trim(listAdd)) then - call shr_string_abort(subName//'ERROR: temp string not large enough') - end if - - call shr_string_clean(l1) - l1 = trim(listadd) - call shr_string_leftAlign(l1,rCode) - if (len_trim(list)+len_trim(l1)+1 > len(list)) & - call shr_string_abort(subName//'ERROR: output list string not large enough') - if (len_trim(list) == 0) then - list = trim(l1) - else - list = trim(list)//":"//trim(l1) - endif - - if (present(rc)) rc = rCode - if (debug>1) call shr_timer_stop (t01) - -end subroutine shr_string_listAppend - -!=============================================================================== -!BOP =========================================================================== -! -! !IROUTINE: shr_string_listPrepend -- Prepend one list to another -! -! !DESCRIPTION: -! Prepend one list to another -! \newline -! call shr\_string\_listPrepend(listadd,list) -! \newline -! results in listadd:list -! -! !REVISION HISTORY: -! 2005-May-05 - T. Craig -! -! !INTERFACE: ------------------------------------------------------------------ - -subroutine shr_string_listPrepend(listadd,list,rc) - - implicit none - -! !INPUT/OUTPUT PARAMETERS: - - character(*) ,intent(in) :: listadd ! list/string - character(*) ,intent(inout) :: list ! list/string - integer(SHR_KIND_IN),optional,intent(out) :: rc ! return code - -!EOP - - !----- local ----- - character(SHR_KIND_CX) :: l1 ! local string - integer(SHR_KIND_IN) :: rCode ! return code - integer(SHR_KIND_IN) :: t01 = 0 ! timer - - !----- formats ----- - character(*),parameter :: subName = "(shr_string_listPrepend) " - character(*),parameter :: F00 = "('(shr_string_listPrepend) ',4a)" - -!------------------------------------------------------------------------------- -! Notes: -! - no input or output string should be longer than SHR_KIND_CX -!------------------------------------------------------------------------------- - - if (debug>1 .and. t01<1) call shr_timer_get(t01,subName) - if (debug>1) call shr_timer_start(t01) - rCode = 0 - - !--- make sure temp string is large enough --- - if (len(l1) < len_trim(listAdd)) then - call shr_string_abort(subName//'ERROR: temp string not large enough') - end if - - call shr_string_clean(l1) - l1 = trim(listadd) - call shr_string_leftAlign(l1,rCode) - call shr_string_leftAlign(list,rCode) - if (len_trim(list)+len_trim(l1)+1 > len(list)) & - call shr_string_abort(subName//'ERROR: output list string not large enough') - if (len_trim(l1) == 0) then - list = trim(list) - else - list = trim(l1)//":"//trim(list) - endif - - if (present(rc)) rc = rCode - if (debug>1) call shr_timer_stop (t01) - -end subroutine shr_string_listPrepend - -!=============================================================================== -!BOP =========================================================================== -! -! !IROUTINE: shr_string_listGetIndexF -- Get index of field in string -! -! !DESCRIPTION: -! Get index of field in string -! \newline -! k = shr\_string\_listGetIndex(str,"taux") -! -! !REVISION HISTORY: -! 2005-Feb-28 - B. Kauffman and J. Schramm - first version -! -! !INTERFACE: ------------------------------------------------------------------ - -integer function shr_string_listGetIndexF(string,fldStr) - - implicit none - -! !INPUT/OUTPUT PARAMETERS: - - character(*),intent(in) :: string ! string - character(*),intent(in) :: fldStr ! name of field - -!EOP - - !----- local ----- - integer(SHR_KIND_IN) :: k ! local index variable - integer(SHR_KIND_IN) :: rc ! error code - integer(SHR_KIND_IN) :: t01 = 0 ! timer - - !----- formats ----- - character(*),parameter :: subName = "(shr_string_listGetIndexF) " - character(*),parameter :: F00 = "('(shr_string_listGetIndexF) ',4a)" - -!------------------------------------------------------------------------------- - - if (debug>1 .and. t01<1) call shr_timer_get(t01,subName) - if (debug>1) call shr_timer_start(t01) - - call shr_string_listGetIndex(string,fldStr,k,print=.false.,rc=rc) - shr_string_listGetIndexF = k - - if (debug>1) call shr_timer_stop (t01) - -end function shr_string_listGetIndexF - -!=============================================================================== -!BOP =========================================================================== -! -! !IROUTINE: shr_string_listGetIndex -- Get index of field in string -! -! !DESCRIPTION: -! Get index of field in string -! \newline -! call shr\_string\_listGetIndex(str,"taux",k,rc) -! -! !REVISION HISTORY: -! 2005-Feb-28 - B. Kauffman and J. Schramm - first version -! -! !INTERFACE: ------------------------------------------------------------------ - -subroutine shr_string_listGetIndex(string,fldStr,kFld,print,rc) - - implicit none - -! !INPUT/OUTPUT PARAMETERS: - - character(*) ,intent(in) :: string ! string - character(*) ,intent(in) :: fldStr ! name of field - integer(SHR_KIND_IN),intent(out) :: kFld ! index of field - logical ,intent(in) ,optional :: print ! print switch - integer(SHR_KIND_IN),intent(out),optional :: rc ! return code - -!EOP - - !----- local ----- - integer(SHR_KIND_IN) :: n ! index for colon position - integer(SHR_KIND_IN) :: k ! index for field name position - integer(SHR_KIND_IN) :: nFields ! number of fields in a string - integer(SHR_KIND_IN) :: i0,i1 ! fldStr == string(i0,i1) ?? - integer(SHR_KIND_IN) :: j0,j1 ! fldStr == string(j0,j1) ?? - logical :: found ! T => field found in fieldNames - logical :: lprint ! local print flag - integer(SHR_KIND_IN) :: t01 = 0 ! timer - - !----- formats ----- - character(*),parameter :: subName = "(shr_string_listGetIndex) " - character(*),parameter :: F00 = "('(shr_string_listGetIndex) ',4a)" - -!------------------------------------------------------------------------------- -! Notes: -! - searching from both ends of the list at the same time seems to be 20% faster -! but I'm not sure why (B. Kauffman, Feb 2007) -! - I commented out sanity check to a little gain speed (B. Kauffman, Mar 2007) -!------------------------------------------------------------------------------- - - if (debug>1 .and. t01<1) call shr_timer_get(t01,subName) - if (debug>1) call shr_timer_start(t01) - if (present(rc)) rc = 0 - - lprint = .false. - if (present(print)) lprint = print - - !--- confirm proper size of input data --- - if (len_trim(fldStr) < 1) then - if (lprint) write(s_logunit,F00) "ERROR: input field name has 0 length" - call shr_string_abort(subName//"invalid field name") - end if - - !--- search for field name in string's list of fields --- - found = .false. - kFld = 0 - i0 = 1 ! ?? fldStr == string(i0:i1) ?? - i1 = -1 - j0 = -1 ! ?? fldStr == string(j0:j1) ?? - j1 = len_trim(string) - nFields = shr_string_listGetNum(string) - do k = 1,nFields - !-------------------------------------------------------- - ! search from end of list to end of list - !-------------------------------------------------------- - !--- get end index of of field number k --- - n = index(string(i0:len_trim(string)),listDel) - if (n > 0) then - i1 = i0 + n - 2 ! *not* the last field name in fieldNames - else - i1 = len_trim(string) ! this is the last field name in fieldNames - endif - !--- sanity check --- - ! if ((k 0)) then - ! call shr_string_abort(subName//"ERROR: wrong string%nf ?") - ! end if - !--- is it a match? --- - if (trim(fldStr) == string(i0:i1)) then - found = .true. - kFld = k - exit - endif - i0 = i1 + 2 ! start index for next iteration - !-------------------------------------------------------- - ! search from end of list to start of list - !-------------------------------------------------------- - !--- get start index of field number (nFields + 1 - k ) --- - n = index(string(1:j1),listDel,back=.true.) - j0 = n + 1 ! n==0 => the first field name in fieldNames - !--- sanity check --- - ! if ((k 0)) then - ! call shr_string_abort(subName//"ERROR: wrong string%nf ?") - ! end if - !--- is it a match? --- - if (trim(fldStr) == string(j0:j1)) then - found = .true. - kFld = nFields + 1 - k - exit - endif - j1 = j0 - 2 ! end index for next iteration - !-------------------------------------------------------- - ! exit if all field names have been checked - !-------------------------------------------------------- - if (2*k >= nFields) exit - end do - - !--- not finding a field is not a fatal error --- - if (.not. found) then - kFld = 0 - if (lprint .and. s_loglev > 0) write(s_logunit,F00) "FYI: field ",trim(fldStr)," not found in list ",trim(string) - if (present(rc)) rc = 1 - end if - - if (debug>1) call shr_timer_stop (t01) - -end subroutine shr_string_listGetIndex - -!=============================================================================== -!BOP =========================================================================== -! -! !IROUTINE: shr_string_listGetNum -- get number of fields in a string list -! -! !DESCRIPTION: -! return number of fields in string list -! -! !REVISION HISTORY: -! 2005-Apr-28 - T. Craig - First version -! -! !INTERFACE: ------------------------------------------------------------------ - -integer function shr_string_listGetNum(str) - - implicit none - -! !INPUT/OUTPUT PARAMETERS: - - character(*),intent(in) :: str ! string to search - -!EOP - - !----- local ----- - integer(SHR_KIND_IN) :: count ! counts occurances of char - integer(SHR_KIND_IN) :: t01 = 0 ! timer - - !----- formats ----- - character(*),parameter :: subName = "(shr_string_listGetNum) " - character(*),parameter :: F00 = "('(shr_string_listGetNum) ',4a)" - -!------------------------------------------------------------------------------- -! Notes: -!------------------------------------------------------------------------------- - - if (debug>1 .and. t01<1) call shr_timer_get(t01,subName) - if (debug>1) call shr_timer_start(t01) - - shr_string_listGetNum = 0 - - if (len_trim(str) > 0) then - count = shr_string_countChar(str,listDel) - shr_string_listGetNum = count + 1 - endif - - if (debug>1) call shr_timer_stop (t01) - -end function shr_string_listGetNum - -!=============================================================================== -!BOP =========================================================================== -! -! !IROUTINE: shr_string_listSetDel -- Set list delimeter character -! -! !DESCRIPTION: -! Set field delimeter character in lists -! \newline -! call shr\_string\_listSetDel(":") -! -! !REVISION HISTORY: -! 2005-Apr-30 - T. Craig - first prototype -! -! !INTERFACE: ------------------------------------------------------------------ - -subroutine shr_string_listSetDel(cflag) - - implicit none - -! !INPUT/OUTPUT PARAMETERS: - - character(len=1),intent(in) :: cflag - -!EOP - - integer(SHR_KIND_IN) :: t01 = 0 ! timer - - !--- formats --- - character(*),parameter :: subName = "(shr_string_listSetDel) " - character(*),parameter :: F00 = "('(shr_string_listSetDel) ',a) " - -!------------------------------------------------------------------------------- - - if (debug>1 .and. t01<1) call shr_timer_get(t01,subName) - if (debug>1) call shr_timer_start(t01) - - if (debug > 0 .and. s_loglev > 0) write(s_logunit,F00) 'changing listDel from '//trim(listDel)//' to '//trim(cflag) - listDel = trim(cflag) - listDel2 = listDel//listDel - - if (debug>1) call shr_timer_stop (t01) - -end subroutine shr_string_listSetDel - -!=============================================================================== -!BOP =========================================================================== -! -! !IROUTINE: shr_string_listGetDel -- Get list delimeter character -! -! !DESCRIPTION: -! Get field delimeter character in lists -! \newline -! call shr\_string\_listGetDel(del) -! -! !REVISION HISTORY: -! 2005-May-15 - T. Craig - first prototype -! -! !INTERFACE: ------------------------------------------------------------------ - -subroutine shr_string_listGetDel(del) - - implicit none - -! !INPUT/OUTPUT PARAMETERS: - - character(*),intent(out) :: del - -!EOP - - integer(SHR_KIND_IN) :: t01 = 0 ! timer - - !--- formats --- - character(*),parameter :: subName = "(shr_string_listGetDel) " - character(*),parameter :: F00 = "('(shr_string_listGetDel) ',a) " - -!------------------------------------------------------------------------------- - - if (debug>1 .and. t01<1) call shr_timer_get(t01,subName) - if (debug>1) call shr_timer_start(t01) - - del = trim(listDel) - - if (debug>1) call shr_timer_stop (t01) - -end subroutine shr_string_listGetDel - -!=============================================================================== -!BOP =========================================================================== -! -! !IROUTINE: shr_string_setAbort -- Set local shr_string abort flag -! -! !DESCRIPTION: -! Set local shr_string abort flag, true = abort, false = print and continue -! \newline -! call shr\_string\_setAbort(.false.) -! -! !REVISION HISTORY: -! 2005-Apr-30 - T. Craig - first prototype -! -! !INTERFACE: ------------------------------------------------------------------ - -subroutine shr_string_setAbort(flag) - - implicit none - -! !INPUT/OUTPUT PARAMETERS: - - logical,intent(in) :: flag - -!EOP - - integer(SHR_KIND_IN) :: t01 = 0 ! timer - - !--- formats --- - character(*),parameter :: subName = "(shr_string_setAbort) " - character(*),parameter :: F00 = "('(shr_string_setAbort) ',a) " - -!------------------------------------------------------------------------------- - - if (debug>1 .and. t01<1) call shr_timer_get(t01,subName) - if (debug>1) call shr_timer_start(t01) - - if (debug > 0 .and. s_loglev > 0) then - if (flag) then - write(s_logunit,F00) 'setting abort to true' - else - write(s_logunit,F00) 'setting abort to false' - endif - endif - - doabort = flag - - if (debug>1) call shr_timer_stop (t01) - -end subroutine shr_string_setAbort - -!=============================================================================== -!BOP =========================================================================== -! -! !IROUTINE: shr_string_setDebug -- Set local shr_string debug level -! -! !DESCRIPTION: -! Set local shr_string debug level, 0 = production -! \newline -! call shr\_string\_setDebug(2) -! -! !REVISION HISTORY: -! 2005-Apr-30 - T. Craig - first prototype -! -! !INTERFACE: ------------------------------------------------------------------ - -subroutine shr_string_setDebug(iFlag) - - implicit none - -! !INPUT/OUTPUT PARAMETERS: - - integer(SHR_KIND_IN),intent(in) :: iFlag ! requested debug level - -!EOP - - !--- local --- - integer(SHR_KIND_IN) :: t01 = 0 ! timer - - !--- formats --- - character(*),parameter :: subName = "(shr_string_setDebug) " - character(*),parameter :: F00 = "('(shr_string_setDebug) ',a) " - character(*),parameter :: F01 = "('(shr_string_setDebug) ',a,i3,a,i3) " - -!------------------------------------------------------------------------------- -! NTOE: write statement can be expensive if called many times. -!------------------------------------------------------------------------------- - - if (iFlag>1 .and. t01<1) call shr_timer_get(t01,subName) - if (iFlag>1) call shr_timer_start(t01) - -! if (s_loglev > 0) write(s_logunit,F01) 'changing debug level from ',debug,' to ',iflag - debug = iFlag - - if (iFlag>1) call shr_timer_stop (t01) - -end subroutine shr_string_setDebug - -!=============================================================================== -!=============================================================================== - -subroutine shr_string_abort(string) - - implicit none - -! !INPUT/OUTPUT PARAMETERS: - - character(*),optional,intent(in) :: string - -!EOP - - integer(SHR_KIND_IN) :: t01 = 0 ! timer - - !--- local --- - character(SHR_KIND_CX) :: lstring - character(*),parameter :: subName = "(shr_string_abort)" - character(*),parameter :: F00 = "('(shr_string_abort) ',a)" - -!------------------------------------------------------------------------------- -! NOTE: -! - no input or output string should be longer than SHR_KIND_CX -!------------------------------------------------------------------------------- - - if (debug>1 .and. t01<1) call shr_timer_get(t01,subName) - if (debug>1) call shr_timer_start(t01) - - lstring = '' - if (present(string)) lstring = string - - if (doabort) then - call shr_sys_abort(trim(lstring)) - else - write(s_logunit,F00) ' no abort:'//trim(lstring) - endif - - if (debug>1) call shr_timer_stop (t01) - -end subroutine shr_string_abort - -!=============================================================================== -!=============================================================================== - -end module shr_string_mod diff --git a/tools/mksurfdata_map/src/shr_sys_mod.F90 b/tools/mksurfdata_map/src/shr_sys_mod.F90 deleted file mode 100644 index 8c51b711cc..0000000000 --- a/tools/mksurfdata_map/src/shr_sys_mod.F90 +++ /dev/null @@ -1,352 +0,0 @@ -!=============================================================================== - -MODULE shr_sys_mod - - use shr_kind_mod ! defines real & integer kinds - use shr_log_mod, only: s_loglev => shr_log_Level - use shr_log_mod, only: s_logunit => shr_log_Unit - - implicit none - -! PUBLIC: Public interfaces - - private - - public :: shr_sys_system ! make a system call - public :: shr_sys_chdir ! change current working dir - public :: shr_sys_getenv ! get an environment variable - public :: shr_sys_abort ! abort a program - public :: shr_sys_irtc ! returns real-time clock tick - public :: shr_sys_sleep ! have program sleep for a while - public :: shr_sys_flush ! flush an i/o buffer - -!=============================================================================== -CONTAINS -!=============================================================================== - -!=============================================================================== -!=============================================================================== - -SUBROUTINE shr_sys_system(str,rcode) - - IMPLICIT none - - !----- arguments --- - character(*) ,intent(in) :: str ! system/shell command string - integer(SHR_KIND_IN),intent(out) :: rcode ! function return error code - - !----- functions ----- -#if (defined CRAY) || (defined UNICOSMP) - integer(SHR_KIND_IN),external :: ishell ! function to envoke shell command -#endif -#if (defined OSF1 || defined SUNOS || (defined LINUX && !defined __GFORTRAN__ && !defined CATAMOUNT)) - integer(SHR_KIND_IN),external :: system ! function to envoke shell command -#endif - - !----- local ----- -#if (defined CATAMOUNT) - character(2*SHR_KIND_CL) :: file1 ! one or two filenames - character( SHR_KIND_CL) :: file2 ! 2nd file name - integer(SHR_KIND_IN) :: iloc ! index/location within a string -#endif - - !----- formats ----- - character(*),parameter :: subName = '(shr_sys_system) ' - character(*),parameter :: F00 = "('(shr_sys_system) ',4a)" - -!------------------------------------------------------------------------------- -! PURPOSE: an architecture independant system call -! NOTE: -! - for Catamount (Cray, pheonix at ORNL) there is no system call -- workarounds -! exist only for simple "rm" and "cp" commands -!------------------------------------------------------------------------------- - - -#if (defined CRAY) || (defined UNICOSMP) - - rcode=ishell(str) - -#elif (defined IRIX64 || defined NEC_SX) - - rcode = 0 - call system(str) - -#elif (defined AIX) - - call system(str,rcode) - -#elif (defined OSF1 || defined SUNOS || defined __GFORTRAN__ || (defined LINUX && !defined CATAMOUNT)) - - rcode = system(str) - -#elif (defined CATAMOUNT) - if (str(1:3) == 'rm ') then - call unlink(str(4:)) - if (s_loglev > 0) write(s_logunit,F00) 'CATAMOUNT unlink ',trim(str(4:)) - rcode = 0 - elseif (str(1:3) == 'mv ') then - file1 = str(4:) - iloc = index(file1,' ') + 3 - if (iloc < 6) then - if (s_loglev > 0) write(s_logunit,*) 'CATAMOUNT mv error ',trim(str),iloc - rcode = -1 - else - file1 = str(4:iloc) - file2 = str(iloc+1:) - call rename(trim(file1),trim(file2)) - if (s_loglev > 0) write(s_logunit,F00) 'CATAMOUNT rename ',trim(file1)," ",trim(file2) - rcode = 0 - endif - else - rcode = -1 - endif - -#else - - write(s_logunit,F00) 'ERROR: no implementation of system call for this architecture' - call shr_sys_abort(subName//'no implementation of system call for this architecture') - -#endif - -END SUBROUTINE shr_sys_system - -!=============================================================================== -!=============================================================================== - -SUBROUTINE shr_sys_chdir(path, rcode) - - IMPLICIT none - - !----- arguments ----- - character(*) ,intent(in) :: path ! chdir to this dir - integer(SHR_KIND_IN),intent(out) :: rcode ! return code - - !----- local ----- - integer(SHR_KIND_IN) :: lenpath ! length of path -#if (defined AIX || defined OSF1 || defined SUNOS || (defined LINUX && !defined __GFORTRAN__) || defined NEC_SX) - integer(SHR_KIND_IN),external :: chdir ! AIX system call -#endif - - !----- formats ----- - character(*),parameter :: subName = '(shr_sys_chdir) ' - character(*),parameter :: F00 = "('(shr_sys_chdir) ',4a)" - -!------------------------------------------------------------------------------- -! PURPOSE: an architecture independant system call -!------------------------------------------------------------------------------- - - lenpath=len_trim(path) - -#if (defined IRIX64 || defined CRAY || defined UNICOSMP) - - call pxfchdir(path, lenpath, rcode) - -#elif (defined AIX) - - rcode = chdir(%ref(path(1:lenpath)//'\0')) - -#elif (defined OSF1 || defined SUNOS || defined LINUX || defined NEC_SX) - - rcode=chdir(path(1:lenpath)) - -#else - - write(s_logunit,F00) 'ERROR: no implementation of chdir for this architecture' - call shr_sys_abort(subname//'no implementation of chdir for this machine') - -#endif - -END SUBROUTINE shr_sys_chdir - -!=============================================================================== -!=============================================================================== - -SUBROUTINE shr_sys_getenv(name, val, rcode) - - IMPLICIT none - - !----- arguments ----- - character(*) ,intent(in) :: name ! env var name - character(*) ,intent(out) :: val ! env var value - integer(SHR_KIND_IN),intent(out) :: rcode ! return code - - !----- local ----- - integer(SHR_KIND_IN) :: lenname ! length of env var name - integer(SHR_KIND_IN) :: lenval ! length of env var value - character(SHR_KIND_CL) :: tmpval ! temporary env var value - - !----- formats ----- - character(*),parameter :: subName = '(shr_sys_getenv) ' - character(*),parameter :: F00 = "('(shr_sys_getenv) ',4a)" - -!------------------------------------------------------------------------------- -! PURPOSE: an architecture independant system call -!------------------------------------------------------------------------------- - - lenname=len_trim(name) - -#if (defined IRIX64 || defined CRAY || defined UNICOSMP) - - call pxfgetenv(name, lenname, val, lenval, rcode) - -#elif (defined AIX || defined OSF1 || defined SUNOS || defined LINUX || defined NEC_SX) - - call getenv(trim(name),tmpval) - val=trim(tmpval) - rcode = 0 - if (len_trim(val) == 0 ) rcode = 1 - if (len_trim(val) > SHR_KIND_CL) rcode = 2 - -#else - - write(s_logunit,F00) 'ERROR: no implementation of getenv for this architecture' - call shr_sys_abort(subname//'no implementation of getenv for this machine') - -#endif - -END SUBROUTINE shr_sys_getenv - -!=============================================================================== -!=============================================================================== - -SUBROUTINE shr_sys_abort(string,rc) - - IMPLICIT none - - character(*) ,optional :: string ! error message string - integer(SHR_KIND_IN),optional :: rc ! error code - - !----- formats ----- - character(*),parameter :: subName = '(shr_sys_abort) ' - character(*),parameter :: F00 = "('(shr_sys_abort) ',4a)" - -!------------------------------------------------------------------------------- -! PURPOSE: consistent stopping mechanism -!------------------------------------------------------------------------------- - - call shr_sys_flush(s_logunit) - if (len_trim(string) > 0) write(s_logunit,F00) 'ERROR: '//trim(string) - write(s_logunit,F00) 'WARNING: stopping' - call shr_sys_flush(s_logunit) - call abort() - stop - -END SUBROUTINE shr_sys_abort - -!=============================================================================== -!=============================================================================== - -integer(SHR_KIND_I8) FUNCTION shr_sys_irtc( rate ) - - IMPLICIT none - - !----- arguments ----- - integer(SHR_KIND_I8), optional :: rate - - !----- local ----- - integer(SHR_KIND_IN) :: count - integer(SHR_KIND_IN) :: count_rate - integer(SHR_KIND_IN) :: count_max - integer(SHR_KIND_IN),save :: last_count = -1 - integer(SHR_KIND_I8),save :: count_offset = 0 - - !----- formats ----- - character(*),parameter :: subName = '(shr_sys_irtc) ' - character(*),parameter :: F00 = "('(shr_sys_irtc) ',4a)" - -!------------------------------------------------------------------------------- -! emulates Cray/SGI irtc function (returns clock tick since last reboot) -!------------------------------------------------------------------------------- - - call system_clock(count=count,count_rate=count_rate, count_max=count_max) - if ( present(rate) ) rate = count_rate - shr_sys_irtc = count - - !--- adjust for clock wrap-around --- - if ( last_count /= -1 ) then - if ( count < last_count ) count_offset = count_offset + count_max - end if - shr_sys_irtc = shr_sys_irtc + count_offset - last_count = count - -END FUNCTION shr_sys_irtc - -!=============================================================================== -!=============================================================================== - -SUBROUTINE shr_sys_sleep(sec) - - IMPLICIT none - - !----- arguments ----- - real (SHR_KIND_R8),intent(in) :: sec ! number of seconds to sleep - - !----- local ----- - integer(SHR_KIND_IN) :: isec ! integer number of seconds - integer(SHR_KIND_IN) :: rcode ! return code - character(90) :: str ! system call string - - !----- formats ----- - character(*),parameter :: subName = '(shr_sys_sleep) ' - character(*),parameter :: F00 = "('(shr_sys_sleep) ',4a)" - character(*),parameter :: F10 = "('sleep ',i8 )" - -!------------------------------------------------------------------------------- -! PURPOSE: Sleep for approximately sec seconds -!------------------------------------------------------------------------------- - - isec = nint(sec) - - if (isec < 0) then - if (s_loglev > 0) write(s_logunit,F00) 'ERROR: seconds must be > 0, sec=',sec - else if (isec == 0) then - ! Don't consider this an error and don't call system sleep - else -#if defined(CATAMOUNT) - call sleep(isec) -#else - write(str,FMT=F10) isec - call shr_sys_system( str, rcode ) -#endif - endif - -END SUBROUTINE shr_sys_sleep - -!=============================================================================== -!=============================================================================== - -SUBROUTINE shr_sys_flush(unit) - - IMPLICIT none - - !----- arguments ----- - integer(SHR_KIND_IN) :: unit ! flush output buffer for this unit - - !----- formats ----- - character(*),parameter :: subName = '(shr_sys_flush) ' - character(*),parameter :: F00 = "('(shr_sys_flush) ',4a)" - -!------------------------------------------------------------------------------- -! PURPOSE: an architecture independant system call -!------------------------------------------------------------------------------- - -#if (defined IRIX64 || defined CRAY || defined OSF1 || defined SUNOS || defined LINUX || defined NEC_SX || defined UNICOSMP) - - call flush(unit) - -#elif (defined AIX) - - call flush_(unit) - -#else - - if (s_loglev > 0) write(s_logunit,F00) 'WARNING: no implementation of flush for this architecture' - -#endif - -END SUBROUTINE shr_sys_flush - -!=============================================================================== -!=============================================================================== - -END MODULE shr_sys_mod diff --git a/tools/mksurfdata_map/src/shr_timer_mod.F90 b/tools/mksurfdata_map/src/shr_timer_mod.F90 deleted file mode 100644 index c9d728ca4a..0000000000 --- a/tools/mksurfdata_map/src/shr_timer_mod.F90 +++ /dev/null @@ -1,425 +0,0 @@ -!=============================================================================== - -module shr_timer_mod - - !---------------------------------------------------------------------------- - ! - ! routines that support multiple CPU timers via F90 intrinsics - ! - ! Note: - ! o if an operation is requested on an invalid timer number n - ! then nothing is done in a routine - ! o if more than max_timers are requested, - ! then timer n=max_timers is "overloaded" and becomes invalid/undefined - ! - ! * cpp if-defs were introduced in 2005 to work-around a bug in the ORNL Cray - ! X1 F90 intrinsic system_clock() function -- ideally this Cray bug would be - ! fixed and cpp if-defs would be unnecessary and removed. - ! - ! !REVISION HISTORY: - ! 2005-??-?? - added workaround for Cray F90 bug, mods by Cray/ORNL - ! 2000-??-?? - 1st version by B. Kauffman - !---------------------------------------------------------------------------- - - use shr_kind_mod - use shr_log_mod, only: s_loglev => shr_log_Level - use shr_log_mod, only: s_logunit => shr_log_Unit - - implicit none - - private ! restricted access - - public :: shr_timer_init - public :: shr_timer_get - public :: shr_timer_start - public :: shr_timer_stop - public :: shr_timer_print - public :: shr_timer_print_all - public :: shr_timer_check - public :: shr_timer_check_all - public :: shr_timer_zero - public :: shr_timer_zero_all - public :: shr_timer_free - public :: shr_timer_free_all - public :: shr_timer_sleep - - integer(SHR_KIND_IN),parameter :: stat_free = 0 ! timer status constants - integer(SHR_KIND_IN),parameter :: stat_inuse = 1 - integer(SHR_KIND_IN),parameter :: stat_started = 2 - integer(SHR_KIND_IN),parameter :: stat_stopped = 3 - integer(SHR_KIND_IN),parameter :: max_timers = 200 ! max number of timers - - integer(SHR_KIND_IN) :: status (max_timers) ! status of each timer - !---------------------------------------------------------------------------- - ! the following ifdef circumvents a bug in the X1 system_clock function - !---------------------------------------------------------------------------- -#if (defined UNICOSMP) - integer(kind=8) :: cycles1(max_timers) ! cycle number at timer start - integer(kind=8) :: cycles2(max_timers) ! cycle number at timer stop -#else - integer(SHR_KIND_IN) :: cycles1(max_timers) ! cycle number at timer start - integer(SHR_KIND_IN) :: cycles2(max_timers) ! cycle number at timer stop -#endif - integer(SHR_KIND_IN) :: cycles_max = -1 ! max cycles before wrapping - character (len=80) :: name (max_timers) ! name assigned to each timer - real (SHR_KIND_R8) :: dt (max_timers) ! accumulated time - integer(SHR_KIND_IN) :: calls (max_timers) ! # of samples in accumulation - real (SHR_KIND_R8) :: clock_rate ! clock_rate: seconds per cycle - - save - -!=============================================================================== - contains -!=============================================================================== - -subroutine shr_timer_init - - !----- local ----- - integer(SHR_KIND_IN) :: cycles ! count rate return by system clock -#if (defined UNICOSMP) - integer(kind=8) :: irtc_rate -#endif - - !----- i/o formats ----- - character(len=*),parameter :: F00 = "('(shr_timer_init) ',a,i5)" - -!------------------------------------------------------------------------------- -! This routine initializes: -! 1) values in all timer array locations -! 2) machine parameters necessary for computing cpu time from F90 intrinsics. -! F90 intrinsic: system_clock(count_rate=cycles, count_max=cycles_max) -!------------------------------------------------------------------------------- - - call shr_timer_free_all - -#if (defined UNICOSMP) - cycles = irtc_rate() -#else - call system_clock(count_rate=cycles, count_max=cycles_max) -#endif - - if (cycles /= 0) then - clock_rate = 1.0_SHR_KIND_R8/real(cycles,SHR_KIND_R8) - else - clock_rate = 0._SHR_KIND_R8 - if (s_loglev > 0) write(s_logunit,F00) 'ERROR: no system clock available' - endif - -end subroutine shr_timer_init - -!=============================================================================== - -subroutine shr_timer_get(n, str) - - !----- arguments ----- - integer(SHR_KIND_IN),intent(out) :: n ! timer number - character (*) ,intent( in) :: str ! text string with timer name - - !----- i/o formats ----- - character(len=*),parameter :: F00 = "('(shr_timer_get) ',a,i5)" - -!----------------------------------------------------------------------- -! search for next free timer -!----------------------------------------------------------------------- - - do n=1,max_timers - if (status(n) == stat_free) then - status(n) = stat_inuse - name (n) = str - calls (n) = 0 - return - endif - end do - - n=max_timers - name (n) = "" - if (s_loglev > 0) write(s_logunit,F00) 'ERROR: exceeded maximum number of timers' - -end subroutine shr_timer_get - -!=============================================================================== - -subroutine shr_timer_start(n) - - !----- arguments ----- - integer(SHR_KIND_IN), intent(in) :: n ! timer number - - !----- local ----- -#if (defined UNICOSMP) - integer(kind=8) :: irtc -#endif - - !----- i/o formats ----- - character(len=*),parameter :: F00 = "('(shr_timer_start) ',a,i5)" - -!----------------------------------------------------------------------- -! This routine starts a given timer. -!----------------------------------------------------------------------- - - if ( n>0 .and. n<=max_timers) then - if (status(n) == stat_started) call shr_timer_stop(n) - - status(n) = stat_started -#if (defined UNICOSMP) - cycles1(n) = irtc() -#else - call system_clock(count=cycles1(n)) -#endif - else - if (s_loglev > 0) write(s_logunit,F00) 'ERROR: invalid timer number: ',n - end if - -end subroutine shr_timer_start - -!=============================================================================== - -subroutine shr_timer_stop(n) - - !----- arguments ----- - integer(SHR_KIND_IN), intent(in) :: n ! timer number - - !----- local ----- - real (SHR_KIND_R8) :: elapse ! elapsed time returned by system counter -#if (defined UNICOSMP) - integer(kind=8) :: irtc -#endif - - !----- i/o formats ----- - character(len=*),parameter :: F00 = "('(shr_timer_stop) ',a,i5)" - -!------------------------------------------------------------------------------- -! This routine stops a given timer, checks for cycle wrapping, computes the -! elapsed time, and accumulates the elapsed time in the dt(n) array -!------------------------------------------------------------------------------- - - if ( n>0 .and. n<=max_timers) then - if ( status(n) == stat_started) then -#if (defined UNICOSMP) - cycles2(n) = irtc() -#else - call system_clock(count=cycles2(n)) -#endif - if (cycles2(n) >= cycles1(n)) then - dt(n) = dt(n) + clock_rate*(cycles2(n) - cycles1(n)) - else - dt(n) = dt(n) + clock_rate*(cycles_max + cycles2(n) - cycles1(n)) - endif - calls (n) = calls(n) + 1 - status(n) = stat_stopped - end if - else - if (s_loglev > 0) write(s_logunit,F00) 'ERROR: invalid timer number: ',n - end if - -end subroutine shr_timer_stop - -!=============================================================================== - -subroutine shr_timer_print(n) - - !----- arguments ----- - integer(SHR_KIND_IN), intent(in) :: n ! timer number - - !----- i/o formats ----- - character(len=*),parameter :: F00 = "('(shr_timer_print) ',a,i5)" - character(len=*),parameter :: F01 = "('(shr_timer_print) timer',i3,& - & ':',i8,' calls,',f10.3,'s, id: ',a)" -!------------------------------------------------------------------------------- -! prints the accumulated time for a given timer -!------------------------------------------------------------------------------- - - if ( n>0 .and. n<=max_timers) then - if (status(n) == stat_started) then - call shr_timer_stop(n) - if (s_loglev > 0) write(s_logunit,F01) n,calls(n),dt(n),trim(name(n)) - call shr_timer_start(n) - else - if (s_loglev > 0) write(s_logunit,F01) n,calls(n),dt(n),trim(name(n)) - endif - else - if (s_loglev > 0) write(s_logunit,F00) 'ERROR: invalid timer number: ',n - end if - -end subroutine shr_timer_print - -!=============================================================================== - -subroutine shr_timer_print_all - - !----- local ----- - integer(SHR_KIND_IN) :: n - - !----- i/o formats ----- - character(len=*),parameter :: F00 = "('(shr_timer_print_all) ',a,i5)" - -!------------------------------------------------------------------------------- -! prints accumulated time for all timers in use -!------------------------------------------------------------------------------- - - if (s_loglev > 0) write(s_logunit,F00) 'print all timing info:' - - do n=1,max_timers - if (status(n) /= stat_free) call shr_timer_print(n) - end do - -end subroutine shr_timer_print_all - -!=============================================================================== - -subroutine shr_timer_zero(n) - - !----- arguments ----- - integer(SHR_KIND_IN), intent(in) :: n ! timer number - - !----- i/o formats ----- - character(len=*),parameter :: F00 = "('(shr_timer_zero) ',a,i5)" - -!------------------------------------------------------------------------------- -! This routine resets a given timer. -!------------------------------------------------------------------------------- - - if ( n>0 .and. n<=max_timers) then - dt(n) = 0.0_SHR_KIND_R8 - calls(n) = 0 - else - if (s_loglev > 0) write(s_logunit,F00) 'ERROR: invalid timer number: ',n - end if - -end subroutine shr_timer_zero - -!=============================================================================== - -subroutine shr_timer_zero_all - - !----- i/o formats ----- - character(len=*),parameter :: F00 = "('(shr_timer_zero_all) ',a,i5)" - -!------------------------------------------------------------------------------- -! This routine resets all timers. -!------------------------------------------------------------------------------- - - dt = 0.0_SHR_KIND_R8 - calls = 0 - -end subroutine shr_timer_zero_all - -!=============================================================================== - -subroutine shr_timer_check(n) - - !----- arguments ----- - integer(SHR_KIND_IN), intent(in) :: n ! timer number - - !----- i/o formats ----- - character(len=*),parameter :: F00 = "('(shr_timer_check) ',a,i5)" - -!------------------------------------------------------------------------------- -! This routine checks a given timer. This is primarily used to -! periodically accumulate time in the timer to prevent timer cycles -! from wrapping around max_cycles. -!------------------------------------------------------------------------------- - - if ( n>0 .and. n<=max_timers) then - if (status(n) == stat_started) then - call shr_timer_stop (n) - call shr_timer_start(n) - endif - else - if (s_loglev > 0) write(s_logunit,F00) 'ERROR: invalid timer number: ',n - end if - -end subroutine shr_timer_check - -!=============================================================================== - -subroutine shr_timer_check_all - - !----- local ----- - integer(SHR_KIND_IN) :: n - - !----- i/o formats ----- - character(len=*),parameter :: F00 = "('(shr_timer_check_all) ',a,i5)" - -!------------------------------------------------------------------------------- -! Call shr_timer_check for all timers in use -!------------------------------------------------------------------------------- - - do n=1,max_timers - if (status(n) == stat_started) then - call shr_timer_stop (n) - call shr_timer_start(n) - endif - end do - -end subroutine shr_timer_check_all - -!=============================================================================== - -subroutine shr_timer_free(n) - - !----- arguments ----- - integer(SHR_KIND_IN),intent(in) :: n ! timer number - - !----- i/o formats ----- - character(len=*),parameter :: F00 = "('(shr_timer_free) ',a,i5)" - -!----------------------------------------------------------------------- -! initialize/free all timer array values -!----------------------------------------------------------------------- - - if ( n>0 .and. n<=max_timers) then - status (n) = stat_free - name (n) = "" - dt (n) = 0.0_SHR_KIND_R8 - cycles1(n) = 0 - cycles2(n) = 0 - else - if (s_loglev > 0) write(s_logunit,F00) 'ERROR: invalid timer number: ',n - end if - -end subroutine shr_timer_free - -!=============================================================================== - -subroutine shr_timer_free_all - - !----- local ----- - integer(SHR_KIND_IN) :: n - - !----- i/o formats ----- - character(len=*),parameter :: F00 = "('(shr_timer_free_all) ',a,i5)" - -!------------------------------------------------------------------------------- -! initialize/free all timer array values -!------------------------------------------------------------------------------- - - do n=1,max_timers - call shr_timer_free(n) - end do - -end subroutine shr_timer_free_all - -!=============================================================================== - -subroutine shr_timer_sleep(sec) - - use shr_sys_mod ! share system calls (namely, shr_sys_sleep) - - !----- local ----- - real (SHR_KIND_R8),intent(in) :: sec ! number of seconds to sleep - -!------------------------------------------------------------------------------- -! Sleep for approximately sec seconds -! -! Note: sleep is typically a system call, hence it is implemented in -! shr_sys_mod, although it probably would only be used in a timing -! context, which is why there is a shr_timer_* wrapper provided here. -!------------------------------------------------------------------------------- - - call shr_sys_sleep(sec) - -end subroutine shr_timer_sleep - -!=============================================================================== -end module shr_timer_mod -!=============================================================================== diff --git a/tools/mksurfdata_map/src/test/CMakeLists.txt b/tools/mksurfdata_map/src/test/CMakeLists.txt deleted file mode 100644 index 78dee7b2b1..0000000000 --- a/tools/mksurfdata_map/src/test/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -add_subdirectory(mkpctPftType_test) -add_subdirectory(mkpftUtils_test) -add_subdirectory(mkpftmod_test) -add_subdirectory(mkgridmap_test) -add_subdirectory(mkindexmap_test) -add_subdirectory(mksoilUtils_test) -add_subdirectory(mkdomain_test) diff --git a/tools/mksurfdata_map/src/test/mkdomain_test/CMakeLists.txt b/tools/mksurfdata_map/src/test/mkdomain_test/CMakeLists.txt deleted file mode 100644 index 401ce6a6f6..0000000000 --- a/tools/mksurfdata_map/src/test/mkdomain_test/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -set (pfunit_sources - test_mkdomain.pf) - -create_pFUnit_test(mkdomainMod test_mkdomain_exe - "${pfunit_sources}" "") - -target_link_libraries(test_mkdomain_exe mksurfdat) diff --git a/tools/mksurfdata_map/src/test/mkdomain_test/test_mkdomain.pf b/tools/mksurfdata_map/src/test/mkdomain_test/test_mkdomain.pf deleted file mode 100644 index fd6a2e1e7b..0000000000 --- a/tools/mksurfdata_map/src/test/mkdomain_test/test_mkdomain.pf +++ /dev/null @@ -1,93 +0,0 @@ -module test_mkdomain - - ! Tests of mkdomainMod - - use funit - - use shr_kind_mod, only : r8 => shr_kind_r8 - use mkgridmapMod, only : gridmap_type, for_test_create_gridmap - use mkdomainMod - - implicit none - save - - @TestCase - type, extends(TestCase) :: TestMkDomain - type(domain_type) :: ldomain - contains - procedure :: setUp - procedure :: tearDown - end type TestMkDomain - - integer, parameter :: ns = 2 - -contains - - subroutine setUp(this) - class(TestMkDomain), intent(inout) :: this - - call for_test_create_domain(this%ldomain) - end subroutine setUp - - subroutine tearDown(this) - class(TestMkDomain), intent(inout) :: this - - call domain_clean(this%ldomain) - - end subroutine tearDown - - @Test - subroutine test_runmkdomain(this) - class(TestMkDomain), intent(inout) :: this - - call domain_check( this%ldomain ) - - end subroutine test_runmkdomain - - @Test - subroutine test_is_neglong_domain_0to360(this) - class(TestMkDomain), intent(inout) :: this - - logical :: result - - result = is_domain_0to360_longs( this%ldomain ) - @assertFalse( result ) - end subroutine test_is_neglong_domain_0to360 - - @Test - subroutine test_is_posto360_domain_0to360(this) - class(TestMkDomain), intent(inout) :: this - - logical :: result - - this%ldomain%lonc(1) = 0.0_r8 - this%ldomain%lonc(2) = 360.0_r8 - result = is_domain_0to360_longs( this%ldomain ) - @assertTrue( result ) - end subroutine test_is_posto360_domain_0to360 - - @Test - subroutine test_is_posto180_domain_0to360(this) - class(TestMkDomain), intent(inout) :: this - - logical :: result - - this%ldomain%lonc(1) = 0.0_r8 - this%ldomain%lonc(2) = 180.0_r8 - result = is_domain_0to360_longs( this%ldomain ) - @assertTrue( result ) - end subroutine test_is_posto180_domain_0to360 - - @Test - subroutine test_is_ge180pos_domain_0to360(this) - class(TestMkDomain), intent(inout) :: this - - logical :: result - - this%ldomain%lonc(1) = 180.0_r8 - this%ldomain%lonc(2) = 200.0_r8 - result = is_domain_0to360_longs( this%ldomain ) - @assertTrue( result ) - end subroutine test_is_ge180pos_domain_0to360 - -end module test_mkdomain diff --git a/tools/mksurfdata_map/src/test/mkgridmap_test/CMakeLists.txt b/tools/mksurfdata_map/src/test/mkgridmap_test/CMakeLists.txt deleted file mode 100644 index 85d936fd33..0000000000 --- a/tools/mksurfdata_map/src/test/mkgridmap_test/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -create_pFUnit_test(mkgridmap test_mkgridmap_exe - "test_mkgridmap.pf" "") - -target_link_libraries(test_mkgridmap_exe mksurfdat) \ No newline at end of file diff --git a/tools/mksurfdata_map/src/test/mkgridmap_test/test_mkgridmap.pf b/tools/mksurfdata_map/src/test/mkgridmap_test/test_mkgridmap.pf deleted file mode 100644 index a15944384f..0000000000 --- a/tools/mksurfdata_map/src/test/mkgridmap_test/test_mkgridmap.pf +++ /dev/null @@ -1,106 +0,0 @@ -module test_mkgridmap - - ! Tests of mkgridmapMod - - use funit - use mkgridmapMod - use shr_kind_mod , only : r8 => shr_kind_r8 - - implicit none - - @TestCase - type, extends(TestCase) :: TestMkGridmap - type(gridmap_type) :: gridmap - contains - procedure :: setUp - procedure :: tearDown - end type TestMkGridmap - - real(r8), parameter :: tol = 1.e-13_r8 - -contains - - subroutine setUp(this) - class(TestMkGridmap), intent(inout) :: this - end subroutine setUp - - subroutine tearDown(this) - class(TestMkGridmap), intent(inout) :: this - - call gridmap_clean(this%gridmap) - end subroutine tearDown - - ! ------------------------------------------------------------------------ - ! Tests of for_test_create_gridmap - ! ------------------------------------------------------------------------ - - @Test - subroutine forTestCreateGridmap_defaultArgs(this) - class(TestMkGridmap), intent(inout) :: this - call for_test_create_gridmap(this%gridmap, na=2, nb=3, ns=4, & - src_indx = [11,11,12,12], & - dst_indx = [21,22,22,23], & - wovr = [1._r8, 0.5_r8, 0.5_r8, 1._r8]) - - @assertEqual(2, this%gridmap%na) - @assertEqual(3, this%gridmap%nb) - @assertEqual(4, this%gridmap%ns) - @assertEqual([11,11,12,12], this%gridmap%src_indx) - @assertEqual([21,22,22,23], this%gridmap%dst_indx) - @assertEqual([1._r8, 0.5_r8, 0.5_r8, 1._r8], this%gridmap%wovr) - @assertEqual([1._r8, 1._r8], this%gridmap%frac_src) - @assertEqual([1._r8, 1._r8, 1._r8], this%gridmap%frac_dst) - - ! Don't bother asserting area, xc, yc, because the default values of those shouldn't - ! matter too much. - end subroutine forTestCreateGridmap_defaultArgs - - @Test - subroutine forTestCreateGridmap_explicitArgs(this) - class(TestMkGridmap), intent(inout) :: this - integer, parameter :: na = 2 - integer, parameter :: nb = 3 - integer, parameter :: ns = 4 - integer, parameter :: src_indx(ns) = [11,11,12,12] - integer, parameter :: dst_indx(ns) = [21,22,22,23] - real(r8), parameter :: wovr(ns) = [1._r8, 0.5_r8, 0.5_r8, 1._r8] - real(r8), parameter :: frac_src(na) = [0.1_r8, 0.0_r8] - real(r8), parameter :: frac_dst(nb) = [0.0_r8, 0.1_r8, 0.1_r8] - real(r8), parameter :: area_src(na) = [0.11_r8, 0.12_r8] - real(r8), parameter :: area_dst(nb) = [0.13_r8, 0.14_r8, 0.15_r8] - real(r8), parameter :: xc_src(na) = [1.1_r8, 1.2_r8] - real(r8), parameter :: xc_dst(nb) = [2.1_r8, 2.2_r8, 2.3_r8] - real(r8), parameter :: yc_src(na) = [3.1_r8, 3.2_r8] - real(r8), parameter :: yc_dst(nb) = [4.1_r8, 4.2_r8, 4.3_r8] - - call for_test_create_gridmap(this%gridmap, na=na, nb=nb, ns=ns, & - src_indx = src_indx, & - dst_indx = dst_indx, & - wovr = wovr, & - frac_src = frac_src, & - frac_dst = frac_dst, & - area_src = area_src, & - area_dst = area_dst, & - xc_src = xc_src, & - xc_dst = xc_dst, & - yc_src = yc_src, & - yc_dst = yc_dst) - - @assertEqual(na, this%gridmap%na) - @assertEqual(nb, this%gridmap%nb) - @assertEqual(ns, this%gridmap%ns) - @assertEqual(src_indx, this%gridmap%src_indx) - @assertEqual(dst_indx, this%gridmap%dst_indx) - @assertEqual(wovr, this%gridmap%wovr) - @assertEqual(frac_src, this%gridmap%frac_src) - @assertEqual(frac_dst, this%gridmap%frac_dst) - @assertEqual(yc_src, this%gridmap%yc_src) - @assertEqual(yc_dst, this%gridmap%yc_dst) - @assertEqual(xc_src, this%gridmap%xc_src) - @assertEqual(xc_dst, this%gridmap%xc_dst) - @assertEqual(area_src, this%gridmap%area_src) - @assertEqual(area_dst, this%gridmap%area_dst) - - end subroutine forTestCreateGridmap_explicitArgs - -end module test_mkgridmap diff --git a/tools/mksurfdata_map/src/test/mkindexmap_test/CMakeLists.txt b/tools/mksurfdata_map/src/test/mkindexmap_test/CMakeLists.txt deleted file mode 100644 index 044d3e4f89..0000000000 --- a/tools/mksurfdata_map/src/test/mkindexmap_test/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -create_pFUnit_test(mkindexmap test_mkindexmap_exe - "test_mkindexmap.pf" "") - -target_link_libraries(test_mkindexmap_exe mksurfdat) \ No newline at end of file diff --git a/tools/mksurfdata_map/src/test/mkindexmap_test/test_mkindexmap.pf b/tools/mksurfdata_map/src/test/mkindexmap_test/test_mkindexmap.pf deleted file mode 100644 index 7f6f1d6745..0000000000 --- a/tools/mksurfdata_map/src/test/mkindexmap_test/test_mkindexmap.pf +++ /dev/null @@ -1,258 +0,0 @@ -module test_mkindexmap - - ! Tests of mkindexmapMod - - use funit - use mkindexmapMod - use mkgridmapMod, only : gridmap_type, for_test_create_gridmap, gridmap_clean - use shr_kind_mod , only : r8 => shr_kind_r8 - - implicit none - - @TestCase - type, extends(TestCase) :: TestMkIndexMap - type(gridmap_type) :: gridmap - contains - procedure :: setUp - procedure :: tearDown - procedure :: createGridmap - procedure :: createGridmap3src1dst - end type TestMkIndexMap - - real(r8), parameter :: tol = 1.e-13_r8 - - integer, parameter :: NODATA_VAL = -999 - -contains - - ! ------------------------------------------------------------------------ - ! Helper routines - ! ------------------------------------------------------------------------ - - - subroutine setUp(this) - class(TestMkIndexMap), intent(inout) :: this - end subroutine setUp - - subroutine tearDown(this) - class(TestMkIndexMap), intent(inout) :: this - call gridmap_clean(this%gridmap) - end subroutine tearDown - - !----------------------------------------------------------------------- - subroutine createGridmap(this, src_indx, dst_indx, wovr, & - na_in, nb_in) - ! - ! !DESCRIPTION: - ! Create this%gridmap - ! - ! !ARGUMENTS: - class(TestMkIndexMap), intent(inout) :: this - - ! The following arrays should all be the same size: - integer, intent(in) :: src_indx(:) - integer, intent(in) :: dst_indx(:) - real(r8), intent(in) :: wovr(:) ! overlap weights - - ! If not present, na is set to max(src_indx) and nb to max(dst_indx) - integer, intent(in), optional :: na_in - integer, intent(in), optional :: nb_in - - ! - ! !LOCAL VARIABLES: - integer :: na - integer :: nb - integer :: ns - - character(len=*), parameter :: subname = 'createGridmap' - !----------------------------------------------------------------------- - - ns = size(wovr) - @assertEqual(ns, size(src_indx)) - @assertEqual(ns, size(dst_indx)) - - if (present(na_in)) then - na = na_in - else - na = maxval(src_indx) - end if - - if (present(nb_in)) then - nb = nb_in - else - nb = maxval(dst_indx) - end if - - call for_test_create_gridmap(this%gridmap, na=na, nb=nb, ns=ns, & - src_indx=src_indx, dst_indx=dst_indx, wovr=wovr) - - end subroutine createGridmap - - !----------------------------------------------------------------------- - subroutine createGridmap3src1dst(this) - ! - ! !DESCRIPTION: - ! Creates a gridmap with 3 src points and 1 dst point. - ! - ! Overlap weights are 0.25, 0.5, 0.25 - ! - ! !ARGUMENTS: - class(TestMkIndexMap), intent(inout) :: this - ! - ! !LOCAL VARIABLES: - - character(len=*), parameter :: subname = 'createGridmap3src1dst' - !----------------------------------------------------------------------- - - call this%createGridmap( & - src_indx = [1, 2, 3], & - dst_indx = [1, 1, 1], & - wovr = [0.25_r8, 0.5_r8, 0.25_r8]) - end subroutine createGridmap3src1dst - - - ! ------------------------------------------------------------------------ - ! Tests of get_max_indices - ! ------------------------------------------------------------------------ - - @Test - subroutine getMaxIndices_maxFirst(this) - class(TestMkIndexMap), intent(inout) :: this - integer :: dst_array(1) - - call this%createGridmap3src1dst() - - call get_max_indices(& - gridmap = this%gridmap, & - src_array = [13, 12, 11], & - dst_array = dst_array, & - nodata = NODATA_VAL, & - mask_src = [1, 1, 1]) - - @assertEqual([13], dst_array) - end subroutine getMaxIndices_maxFirst - - @Test - subroutine getMaxIndices_maxMiddle(this) - class(TestMkIndexMap), intent(inout) :: this - integer :: dst_array(1) - - call this%createGridmap3src1dst() - - call get_max_indices(& - gridmap = this%gridmap, & - src_array = [12, 13, 11], & - dst_array = dst_array, & - nodata = NODATA_VAL, & - mask_src = [1, 1, 1]) - - @assertEqual([13], dst_array) - end subroutine getMaxIndices_maxMiddle - - @Test - subroutine getMaxIndices_maxLast(this) - class(TestMkIndexMap), intent(inout) :: this - integer :: dst_array(1) - - call this%createGridmap3src1dst() - - call get_max_indices(& - gridmap = this%gridmap, & - src_array = [11, 12, 13], & - dst_array = dst_array, & - nodata = NODATA_VAL, & - mask_src = [1, 1, 1]) - - @assertEqual([13], dst_array) - end subroutine getMaxIndices_maxLast - - @Test - subroutine getMaxIndices_noData(this) - class(TestMkIndexMap), intent(inout) :: this - integer :: dst_array(2) - - ! 2 destination points, but all source points map to dest #1 (nothing maps to dest #2) - call this%createGridmap( & - src_indx = [1,2,3], & - dst_indx = [1,1,1], & - wovr = [0.25_r8, 0.5_r8, 0.25_r8], & - nb_in = 2) - - call get_max_indices(& - gridmap = this%gridmap, & - src_array = [11, 12, 13], & - dst_array = dst_array, & - nodata = NODATA_VAL, & - mask_src = [1, 1, 1]) - - @assertEqual([13, NODATA_VAL], dst_array) - end subroutine getMaxIndices_noData - - @Test - subroutine getMaxIndices_noOverlap(this) - class(TestMkIndexMap), intent(inout) :: this - integer :: dst_array(2) - - ! 2 destination points, and the matrix has an overlap with dest #2, but the overlap - ! weight is 0. (I'm not sure this can happen in practice, but I'm also not sure that - ! it can't happen.) - call this%createGridmap( & - src_indx = [1,2,3,3], & - dst_indx = [1,1,1,2], & - wovr = [0.25_r8, 0.5_r8, 0.25_r8, 0._r8]) - - call get_max_indices(& - gridmap = this%gridmap, & - src_array = [11, 12, 13], & - dst_array = dst_array, & - nodata = NODATA_VAL, & - mask_src = [1, 1, 1]) - - @assertEqual([13, NODATA_VAL], dst_array) - end subroutine getMaxIndices_noOverlap - - @Test - subroutine getMaxIndices_bigValNoOverlap(this) - class(TestMkIndexMap), intent(inout) :: this - integer :: dst_array(1) - - ! Overlap weight is 0 for a point with a big value. (I'm not sure this can happen in - ! practice, but I'm also not sure that it can't happen.) - call this%createGridmap( & - src_indx = [1,2,3], & - dst_indx = [1,1,1], & - wovr = [0.5_r8, 0.5_r8, 0._r8]) - - call get_max_indices(& - gridmap = this%gridmap, & - src_array = [11, 12, 13], & - dst_array = dst_array, & - nodata = NODATA_VAL, & - mask_src = [1, 1, 1]) - - @assertEqual([12], dst_array) - end subroutine getMaxIndices_bigValNoOverlap - - @Test - subroutine getMaxIndices_multipleDests(this) - ! Make sure that the source/dest indexing is working right by having multiple source - ! & dest points - class(TestMkIndexMap), intent(inout) :: this - integer :: dst_array(2) - - call this%createGridmap( & - src_indx = [1,2,3,4], & - dst_indx = [1,1,2,2], & - wovr = [0.5_r8, 0.5_r8, 0.5_r8, 0.5_r8]) - - call get_max_indices(& - gridmap = this%gridmap, & - src_array = [11,12,22,21], & - dst_array = dst_array, & - nodata = NODATA_VAL, & - mask_src = [1, 1, 1, 1]) - - @assertEqual([12,22], dst_array) - end subroutine getMaxIndices_multipleDests - -end module test_mkindexmap diff --git a/tools/mksurfdata_map/src/test/mkpctPftType_test/CMakeLists.txt b/tools/mksurfdata_map/src/test/mkpctPftType_test/CMakeLists.txt deleted file mode 100644 index 8fd784c672..0000000000 --- a/tools/mksurfdata_map/src/test/mkpctPftType_test/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -create_pFUnit_test(mkpctPftType test_mkpctPftType_exe - "test_mkpctPftType.pf" "") - -target_link_libraries(test_mkpctPftType_exe mksurfdat) \ No newline at end of file diff --git a/tools/mksurfdata_map/src/test/mkpctPftType_test/test_mkpctPftType.pf b/tools/mksurfdata_map/src/test/mkpctPftType_test/test_mkpctPftType.pf deleted file mode 100644 index 1652a742a2..0000000000 --- a/tools/mksurfdata_map/src/test/mkpctPftType_test/test_mkpctPftType.pf +++ /dev/null @@ -1,253 +0,0 @@ -module test_mkpctPftType - - ! Tests of pct_pft_type - - use funit - - use shr_kind_mod, only : r8 => shr_kind_r8 - use mkpctPftTypeMod - - implicit none - save - - real(r8), parameter :: tol = 1.e-12_r8 - -contains - - @Test - subroutine test_constructor_nonzero() - ! Tests constructor with non-zero area - type(pct_pft_type) :: pct_pft - - pct_pft = pct_pft_type([5._r8, 20._r8, 25._r8], 11, [0._r8, 100._r8, 0._r8]) - - @assertEqual([10._r8, 40._r8, 50._r8], pct_pft%get_pct_p2l(), tolerance=tol) - @assertEqual(50._r8, pct_pft%get_pct_l2g(), tolerance=tol) - @assertEqual(11, pct_pft%get_first_pft_index()) - - end subroutine test_constructor_nonzero - - @Test - subroutine test_constructor_zero() - ! Tests constructor with zero area - type(pct_pft_type) :: pct_pft - real(r8) :: default_pct_p2l(3) - - default_pct_p2l = [0._r8, 100._r8, 0._r8] - - pct_pft = pct_pft_type([0._r8, 0._r8, 0._r8], 11, default_pct_p2l) - @assertEqual(default_pct_p2l, pct_pft%get_pct_p2l()) - @assertEqual(0._r8, pct_pft%get_pct_l2g()) - end subroutine test_constructor_zero - - @Test - subroutine test_constructor_empty() - ! Tests version of constructor with an empty landunit - type(pct_pft_type) :: pct_pft - - pct_pft = pct_pft_type() - @assertEqual(0._r8, pct_pft%get_pct_l2g()) - end subroutine test_constructor_empty - - @Test - subroutine test_assignment() - ! Tests assignment of one object to another - ! - ! Currently there is no defined assignment operator, so the point of this is to - ! ensure that intrinsic assignment works properly, particularly with respect to - ! maintaining the correct lower bound (get_first_pft_index). - type(pct_pft_type) :: source, dest - - source = pct_pft_type([5._r8, 20._r8, 25._r8], 11, [0._r8, 100._r8, 0._r8]) - dest = source - - @assertEqual([10._r8, 40._r8, 50._r8], dest%get_pct_p2l(), tolerance=tol) - @assertEqual(50._r8, dest%get_pct_l2g(), tolerance=tol) - @assertEqual(11, dest%get_first_pft_index()) - end subroutine test_assignment - - @Test - subroutine test_get_pct_p2g() - ! Test the get_pct_p2g routine - type(pct_pft_type) :: pct_pft - - pct_pft = pct_pft_type([5._r8, 20._r8, 25._r8], 11, [0._r8, 100._r8, 0._r8]) - - @assertEqual([5._r8, 20._r8, 25._r8], pct_pft%get_pct_p2g()) - end subroutine test_get_pct_p2g - - @Test - subroutine test_get_one_pct_p2g() - ! Test the get_one_pct_p2g routine - type(pct_pft_type) :: pct_pft - - pct_pft = pct_pft_type([5._r8, 20._r8, 25._r8], 11, [0._r8, 100._r8, 0._r8]) - - @assertEqual(20._r8, pct_pft%get_one_pct_p2g(12)) - end subroutine test_get_one_pct_p2g - - - @Test - subroutine test_set_pct_l2g() - ! Test the set_pct_l2g routine - type(pct_pft_type) :: pct_pft - - pct_pft = pct_pft_type([5._r8, 20._r8, 25._r8], 11, [0._r8, 100._r8, 0._r8]) - - call pct_pft%set_pct_l2g(60._r8) - @assertEqual([10._r8, 40._r8, 50._r8], pct_pft%get_pct_p2l(), tolerance=tol) - @assertEqual(60._r8, pct_pft%get_pct_l2g(), tolerance=tol) - end subroutine test_set_pct_l2g - - - @Test - subroutine test_set_one_pct_p2g() - ! Test the set_one_pct_p2g routine - type(pct_pft_type) :: pct_pft - - pct_pft = pct_pft_type([5._r8, 20._r8, 25._r8], 11, [0._r8, 100._r8, 0._r8]) - - call pct_pft%set_one_pct_p2g(12, 10._r8) - @assertEqual(40._r8, pct_pft%get_pct_l2g(), tolerance=tol) - @assertEqual([12.5_r8, 25._r8, 62.5_r8], pct_pft%get_pct_p2l(), tolerance=tol) - - end subroutine test_set_one_pct_p2g - - @Test - subroutine test_set_one_pct_p2g_to_zero() - ! Test the set_one_pct_p2g routine, when we go to a total area of 0 - type(pct_pft_type) :: pct_pft - - pct_pft = pct_pft_type([20._r8, 0._r8, 0._r8], 11, [0._r8, 100._r8, 0._r8]) - - call pct_pft%set_one_pct_p2g(11, 0._r8) - @assertEqual(0._r8, pct_pft%get_pct_l2g()) - ! note that pct_p2l stays at its original value - @assertEqual([100._r8, 0._r8, 0._r8], pct_pft%get_pct_p2l(), tolerance=tol) - - end subroutine test_set_one_pct_p2g_to_zero - - @Test - subroutine test_set_one_pct_p2g_from_zero() - ! Test the set_one_pct_p2g routine, when we start from a total area of 0 - type(pct_pft_type) :: pct_pft - - pct_pft = pct_pft_type([0._r8, 0._r8, 0._r8], 11, [0._r8, 100._r8, 0._r8]) - - call pct_pft%set_one_pct_p2g(13, 5._r8) - @assertEqual(5._r8, pct_pft%get_pct_l2g()) - @assertEqual([0._r8, 0._r8, 100._r8], pct_pft%get_pct_p2l(), tolerance=tol) - - end subroutine test_set_one_pct_p2g_from_zero - - @Test - subroutine test_merge_pfts() - ! Test the merge_pfts routine - type(pct_pft_type) :: pct_pft - - pct_pft = pct_pft_type([5._r8, 20._r8, 25._r8], 11, [0._r8, 100._r8, 0._r8]) - - call pct_pft%merge_pfts(source=12, dest=13) - @assertEqual(50._r8, pct_pft%get_pct_l2g()) - @assertEqual([10._r8, 0._r8, 90._r8], pct_pft%get_pct_p2l(), tolerance=tol) - end subroutine test_merge_pfts - - @Test - subroutine test_remove_small_cover_no_small() - ! Test the remove_small_cover routine with no small pfts - type(pct_pft_type) :: pct_pft, pct_pft_orig - integer :: nsmall - - pct_pft = pct_pft_type([5._r8, 20._r8, 0._r8], 11, [0._r8, 100._r8, 0._r8]) - pct_pft_orig = pct_pft - - call pct_pft%remove_small_cover(1._r8, nsmall) - @assertEqual(pct_pft_orig%get_pct_l2g(), pct_pft%get_pct_l2g()) - @assertEqual(pct_pft_orig%get_pct_p2l(), pct_pft%get_pct_p2l()) - @assertEqual(0, nsmall) - end subroutine test_remove_small_cover_no_small - - @Test - subroutine test_remove_small_cover_all_small() - ! Test the remove_small_cover routine with all small (or zero) pfts - type(pct_pft_type) :: pct_pft, pct_pft_orig - integer :: nsmall - - pct_pft = pct_pft_type([5._r8, 20._r8, 0._r8], 11, [0._r8, 100._r8, 0._r8]) - pct_pft_orig = pct_pft - - call pct_pft%remove_small_cover(30._r8, nsmall) - @assertEqual(0._r8, pct_pft%get_pct_l2g()) - @assertEqual(pct_pft_orig%get_pct_p2l(), pct_pft%get_pct_p2l()) - @assertEqual(2, nsmall) - end subroutine test_remove_small_cover_all_small - - @Test - subroutine test_remove_small_cover_some_small() - ! Test the remove_small_cover routine with some (but not all) small pfts - type(pct_pft_type) :: pct_pft - integer :: nsmall - - pct_pft = pct_pft_type([5._r8, 20._r8, 0._r8, 25._r8], 11, [0._r8, 100._r8, 0._r8, 0._r8]) - - call pct_pft%remove_small_cover(10._r8, nsmall) - @assertEqual(45._r8, pct_pft%get_pct_l2g()) - @assertEqual([0._r8, 20._r8, 0._r8, 25._r8]/45._r8 * 100._r8, pct_pft%get_pct_p2l(), tolerance=tol) - @assertEqual(1, nsmall) - end subroutine test_remove_small_cover_some_small - - @Test - subroutine test_remove_small_cover_zero_area() - ! Test the remove_small_cover routine with a starting area of 0 - type(pct_pft_type) :: pct_pft - integer :: nsmall - - pct_pft = pct_pft_type([0._r8, 0._r8, 0._r8], 11, [0._r8, 100._r8, 0._r8]) - - call pct_pft%remove_small_cover(1._r8, nsmall) - @assertEqual(0._r8, pct_pft%get_pct_l2g()) - @assertEqual([0._r8, 100._r8, 0._r8], pct_pft%get_pct_p2l()) - @assertEqual(0, nsmall) - end subroutine test_remove_small_cover_zero_area - - @Test - subroutine test_remove_small_cover_no_landunit() - ! Test the remove_small_cover routine when there are no pfts on this landunit - type(pct_pft_type) :: pct_pft - integer :: nsmall - - pct_pft = pct_pft_type() - call pct_pft%remove_small_cover(1._r8, nsmall) - @assertEqual(0._r8, pct_pft%get_pct_l2g()) - @assertEqual(0, nsmall) - end subroutine test_remove_small_cover_no_landunit - - @Test - subroutine test_get_pct_p2l_array() - ! Test the get_pct_p2l_array routine - type(pct_pft_type) :: pct_pft(2) - real(r8) :: expected(2, 3) - - pct_pft(1) = pct_pft_type([10._r8, 40._r8, 50._r8], 11, [0._r8, 100._r8, 0._r8]) - pct_pft(2) = pct_pft_type([5._r8, 30._r8, 65._r8], 11, [0._r8, 100._r8, 0._r8]) - - expected(1,:) = [10._r8, 40._r8, 50._r8] - expected(2,:) = [5._r8, 30._r8, 65._r8] - - @assertEqual(expected, get_pct_p2l_array(pct_pft)) - - end subroutine test_get_pct_p2l_array - - @Test - subroutine test_get_pct_l2g_array() - ! Test the get_pct_l2g_array routine - type(pct_pft_type) :: pct_pft(2) - - pct_pft(1) = pct_pft_type([5._r8, 25._r8, 20._r8], 11, [0._r8, 100._r8, 0._r8]) - pct_pft(2) = pct_pft_type([1._r8, 2._r8, 3._r8], 11, [0._r8, 100._r8, 0._r8]) - - @assertEqual([50._r8, 6._r8], get_pct_l2g_array(pct_pft), tolerance=tol) - - end subroutine test_get_pct_l2g_array - -end module test_mkpctPftType diff --git a/tools/mksurfdata_map/src/test/mkpftUtils_test/CMakeLists.txt b/tools/mksurfdata_map/src/test/mkpftUtils_test/CMakeLists.txt deleted file mode 100644 index 33dd01bcd9..0000000000 --- a/tools/mksurfdata_map/src/test/mkpftUtils_test/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -set (pfunit_sources - test_adjust_total_veg_area.pf - test_convert_from_p2g.pf) - -create_pFUnit_test(mkpftUtils test_mkpftUtils_exe - "${pfunit_sources}" "") - -target_link_libraries(test_mkpftUtils_exe mksurfdat) \ No newline at end of file diff --git a/tools/mksurfdata_map/src/test/mkpftUtils_test/test_adjust_total_veg_area.pf b/tools/mksurfdata_map/src/test/mkpftUtils_test/test_adjust_total_veg_area.pf deleted file mode 100644 index 1223e5bc68..0000000000 --- a/tools/mksurfdata_map/src/test/mkpftUtils_test/test_adjust_total_veg_area.pf +++ /dev/null @@ -1,59 +0,0 @@ -module test_adjust_total_veg_area - - ! Tests of mkpftUtilsMod: adjust_total_veg_area - - use funit - - use shr_kind_mod, only : r8 => shr_kind_r8 - use mkpctPftTypeMod, only : pct_pft_type - use mkpftUtilsMod, only : adjust_total_veg_area - - implicit none - save - - real(r8), parameter :: tol = 1.e-12_r8 - -contains - - @Test - subroutine test_standard_case() - type(pct_pft_type) :: pctnatpft, pctcft - - pctnatpft = pct_pft_type([5._r8, 10._r8], 1, [100._r8, 0._r8]) - pctcft = pct_pft_type([10._r8, 20._r8], 3, [100._r8, 0._r8]) - - call adjust_total_veg_area(90._r8, pctnatpft, pctcft) - - @assertEqual(30._r8, pctnatpft%get_pct_l2g()) - @assertEqual(60._r8, pctcft%get_pct_l2g()) - end subroutine test_standard_case - - @Test - subroutine test_initial_total_zero() - ! When the old areas are 0, all area should go into natural veg - type(pct_pft_type) :: pctnatpft, pctcft - - pctnatpft = pct_pft_type([0._r8, 0._r8], 1, [100._r8, 0._r8]) - pctcft = pct_pft_type([0._r8, 0._r8], 3, [100._r8, 0._r8]) - - call adjust_total_veg_area(90._r8, pctnatpft, pctcft) - - @assertEqual(90._r8, pctnatpft%get_pct_l2g()) - @assertEqual(0._r8, pctcft%get_pct_l2g()) - end subroutine test_initial_total_zero - - @Test - subroutine test_initial_one_zero() - ! Test a case where this is initially a 0 - make sure it stays 0 - type(pct_pft_type) :: pctnatpft, pctcft - - pctnatpft = pct_pft_type([0._r8, 0._r8], 1, [100._r8, 0._r8]) - pctcft = pct_pft_type([10._r8, 20._r8], 3, [100._r8, 0._r8]) - - call adjust_total_veg_area(90._r8, pctnatpft, pctcft) - - @assertEqual(0._r8, pctnatpft%get_pct_l2g()) - @assertEqual(90._r8, pctcft%get_pct_l2g()) - end subroutine test_initial_one_zero - -end module test_adjust_total_veg_area diff --git a/tools/mksurfdata_map/src/test/mkpftUtils_test/test_convert_from_p2g.pf b/tools/mksurfdata_map/src/test/mkpftUtils_test/test_convert_from_p2g.pf deleted file mode 100644 index 3227031726..0000000000 --- a/tools/mksurfdata_map/src/test/mkpftUtils_test/test_convert_from_p2g.pf +++ /dev/null @@ -1,151 +0,0 @@ -module test_convert_from_p2g - - ! Tests of mkpftUtilsMod: convert_from_p2g - - use funit - - use shr_kind_mod, only : r8 => shr_kind_r8 - use mkpctPftTypeMod, only : pct_pft_type - use mkpftUtilsMod, only : convert_from_p2g - use mkpftConstantsMod, only : natpft_lb, natpft_ub, num_cft, cft_lb, cft_ub, c3cropindex - - implicit none - save - - real(r8), parameter :: tol = 1.e-12_r8 - -contains - - subroutine setup() - ! Perform setup for most tests - - natpft_lb = 0 - natpft_ub = 2 - cft_lb = 3 - cft_ub = 4 - num_cft = 2 - - c3cropindex = 3 - - end subroutine setup - - - ! ------------------------------------------------------------------------ - ! Tests of convert_from_p2g_default - ! ------------------------------------------------------------------------ - - @Test - subroutine test_standard() - ! Standard case: some nat pft, some crop - type(pct_pft_type) :: pctnatpft, pctcft - - call setup - - call convert_from_p2g([1._r8, 2._r8, 3._r8, 4._r8, 5._r8], pctnatpft, pctcft) - - @assertEqual(6._r8, pctnatpft%get_pct_l2g(), tolerance=tol) - @assertEqual([1._r8, 2._r8, 3._r8]/6._r8 * 100._r8, pctnatpft%get_pct_p2l(), tolerance=tol) - @assertEqual(9._r8, pctcft%get_pct_l2g(), tolerance=tol) - @assertEqual([4._r8, 5._r8]/9._r8 * 100._r8, pctcft%get_pct_p2l(), tolerance=tol) - end subroutine test_standard - - @Test - subroutine test_natpft0() - ! natpft all 0 (percents should be at their default) - type(pct_pft_type) :: pctnatpft, pctcft - - call setup - - call convert_from_p2g([0._r8, 0._r8, 0._r8, 4._r8, 5._r8], pctnatpft, pctcft) - - @assertEqual(0._r8, pctnatpft%get_pct_l2g()) - @assertEqual([100._r8, 0._r8, 0._r8], pctnatpft%get_pct_p2l()) - @assertEqual(9._r8, pctcft%get_pct_l2g(), tolerance=tol) - @assertEqual([4._r8, 5._r8]/9._r8 * 100._r8, pctcft%get_pct_p2l(), tolerance=tol) - end subroutine test_natpft0 - - @Test - subroutine test_cft0() - ! cft landunit present, but all 0 (percents should be at their default) - type(pct_pft_type) :: pctnatpft, pctcft - - call setup - - call convert_from_p2g([1._r8, 2._r8, 3._r8, 0._r8, 0._r8], pctnatpft, pctcft) - @assertEqual(6._r8, pctnatpft%get_pct_l2g(), tolerance=tol) - @assertEqual([1._r8, 2._r8, 3._r8]/6._r8 * 100._r8, pctnatpft%get_pct_p2l(), tolerance=tol) - @assertEqual(0._r8, pctcft%get_pct_l2g(), tolerance=tol) - @assertEqual([100._r8, 0._r8], pctcft%get_pct_p2l(), tolerance=tol) - end subroutine test_cft0 - - @Test - subroutine test_no_cft_landunit() - ! no cft landunit - type(pct_pft_type) :: pctnatpft, pctcft - - call setup - - cft_lb = 3 - cft_ub = 2 - num_cft = 0 - - call convert_from_p2g([1._r8, 2._r8, 3._r8], pctnatpft, pctcft) - @assertEqual(6._r8, pctnatpft%get_pct_l2g(), tolerance=tol) - @assertEqual([1._r8, 2._r8, 3._r8]/6._r8 * 100._r8, pctnatpft%get_pct_p2l(), tolerance=tol) - @assertEqual(0._r8, pctcft%get_pct_l2g(), tolerance=tol) - - end subroutine test_no_cft_landunit - - ! ------------------------------------------------------------------------ - ! Tests of convert_from_p2g_missing_crops - ! ------------------------------------------------------------------------ - - @Test - subroutine test_missing_crops() - type(pct_pft_type) :: pctnatpft, pctcft_saved, pctcft - - call setup - ! add an extra cft to make sure it's okay for the pct_p2g input to not contain the - ! same number of elements as the cft landunit - cft_ub = 5 - num_cft = 3 - pctcft_saved = pct_pft_type([10._r8, 15._r8, 20._r8], cft_lb, [100._r8, 0._r8, 0._r8]) - - call convert_from_p2g([1._r8, 2._r8, 3._r8, 4._r8, 0._r8], pctcft_saved, pctnatpft, pctcft) - @assertEqual(6._r8, pctnatpft%get_pct_l2g(), tolerance=tol) - @assertEqual([1._r8, 2._r8, 3._r8]/6._r8 * 100._r8, pctnatpft%get_pct_p2l(), tolerance=tol) - @assertEqual(4._r8, pctcft%get_pct_l2g(), tolerance=tol) - @assertEqual([10._r8, 15._r8, 20._r8]/45._r8 * 100._r8, pctcft%get_pct_p2l(), tolerance=tol) - - end subroutine test_missing_crops - - @Test - subroutine test_missing_crops_natpft0() - ! Make sure the setting of the natpft default works correctly for the missing_crops - ! version of the subroutine - type(pct_pft_type) :: pctnatpft, pctcft_saved, pctcft - - call setup - pctcft_saved = pct_pft_type([10._r8, 15._r8], cft_lb, [100._r8, 0._r8]) - - call convert_from_p2g([0._r8, 0._r8, 0._r8, 4._r8, 0._r8], pctcft_saved, pctnatpft, pctcft) - @assertEqual(0._r8, pctnatpft%get_pct_l2g()) - @assertEqual([100._r8, 0._r8, 0._r8], pctnatpft%get_pct_p2l()) - @assertEqual(4._r8, pctcft%get_pct_l2g(), tolerance=tol) - @assertEqual([10._r8, 15._r8]/25._r8 * 100._r8, pctcft%get_pct_p2l(), tolerance=tol) - end subroutine test_missing_crops_natpft0 - - @Test - subroutine test_missing_crops_cft0() - ! Make sure the cft cover is as expected when the cft landunit area goes to 0 - type(pct_pft_type) :: pctnatpft, pctcft_saved, pctcft - - call setup - pctcft_saved = pct_pft_type([10._r8, 15._r8], cft_lb, [100._r8, 0._r8]) - - call convert_from_p2g([1._r8, 2._r8, 3._r8, 0._r8, 0._r8], pctcft_saved, pctnatpft, pctcft) - @assertEqual(0._r8, pctcft%get_pct_l2g(), tolerance=tol) - @assertEqual([10._r8, 15._r8]/25._r8 * 100._r8, pctcft%get_pct_p2l(), tolerance=tol) - end subroutine test_missing_crops_cft0 - -end module test_convert_from_p2g diff --git a/tools/mksurfdata_map/src/test/mkpftmod_test/CMakeLists.txt b/tools/mksurfdata_map/src/test/mkpftmod_test/CMakeLists.txt deleted file mode 100644 index 8fcb75145f..0000000000 --- a/tools/mksurfdata_map/src/test/mkpftmod_test/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -set (pfunit_sources - test_pftrun.pf - test_pft_oride.pf - test_pftInit.pf) - -create_pFUnit_test(mkpftMod test_mkpft_exe - "${pfunit_sources}" "") - -target_link_libraries(test_mkpft_exe mksurfdat) diff --git a/tools/mksurfdata_map/src/test/mkpftmod_test/test_pftInit.pf b/tools/mksurfdata_map/src/test/mkpftmod_test/test_pftInit.pf deleted file mode 100644 index a555e3e8ca..0000000000 --- a/tools/mksurfdata_map/src/test/mkpftmod_test/test_pftInit.pf +++ /dev/null @@ -1,297 +0,0 @@ -module test_pftInit - - ! Tests of mkpftMod: pft_override functions - - use funit - - use shr_kind_mod, only : r8 => shr_kind_r8 - use mkpftMod - use mkvarctl, only: numpft - use mkvarpar, only: numstdpft, noveg - use mkpftConstantsMod, only: maxpft, c3cropindex - - implicit none - save - - @TestCase - type, extends(TestCase) :: TestMkPFT - contains - procedure :: setUp - procedure :: tearDown - end type TestMkPFT - -contains - - subroutine setUp(this) - class(TestMkPFT), intent(inout) :: this - numpft = numstdpft - pft_idx(0:maxpft) = -1 - pft_frc(0:maxpft) = 0.0_r8 - end subroutine setUp - - subroutine tearDown(this) - class(TestMkPFT), intent(inout) :: this - - end subroutine tearDown - - @Test - subroutine test_runmkpftInit(this) - class(TestMkPFT), intent(inout) :: this - logical :: zero_out_l, all_veg_l - - zero_out_l = .false. - all_veg_l = .false. - call mkpftInit( zero_out_l, all_veg_l ) - @assertFalse( use_input_pft ) - @assertFalse( presc_cover ) - - end subroutine test_runmkpftInit - - @Test - subroutine test_runmkpftInitZero(this) - class(TestMkPFT), intent(inout) :: this - logical :: zero_out_l, all_veg_l - - zero_out_l = .true. - all_veg_l = .false. - call mkpftInit( zero_out_l, all_veg_l ) - @assertTrue( use_input_pft ) - @assertTrue( presc_cover ) - @assertEqual( pft_idx(0), noveg ) - @assertEqual( pft_frc(0), 0.0_r8 ) - - end subroutine test_runmkpftInitZero - - @Test - subroutine test_runmkpftInitPftORide(this) - class(TestMkPFT), intent(inout) :: this - logical :: zero_out_l, all_veg_l - - zero_out_l = .false. - pft_idx(0) = 1 - pft_frc(0) = 100._r8 - all_veg_l = .true. - call mkpftInit( zero_out_l, all_veg_l ) - @assertTrue( use_input_pft ) - @assertTrue( presc_cover ) - - end subroutine test_runmkpftInitPftORide - - - @Test - subroutine test_runmkpftInitPftORideButNOTAllVeg(this) - class(TestMkPFT), intent(inout) :: this - logical :: zero_out_l, all_veg_l - - zero_out_l = .false. - pft_idx(0:1) = (/ 1, c3cropindex /) - pft_frc(0:1) = (/ 50._r8, 50.0_r8 /) - all_veg_l = .true. - call mkpftInit( zero_out_l, all_veg_l ) - @assertTrue( use_input_pft ) - @assertTrue( presc_cover ) - - end subroutine test_runmkpftInitPftORideButNOTAllVeg - - - @Test - subroutine test_runmkpftInitPftORideCrop(this) - class(TestMkPFT), intent(inout) :: this - logical :: zero_out_l, all_veg_l - - zero_out_l = .false. - numpft = maxpft - pft_idx(0) = 17 - pft_frc(0) = 100._r8 - all_veg_l = .true. - call mkpftInit( zero_out_l, all_veg_l ) - @assertTrue( use_input_pft ) - @assertTrue( presc_cover ) - - end subroutine test_runmkpftInitPftORideCrop - - - @Test - subroutine test_runmkpftInitPftORideAll(this) - class(TestMkPFT), intent(inout) :: this - logical :: zero_out_l, all_veg_l - integer :: i - - zero_out_l = .false. - numpft = numstdpft - do i = 0, numpft - pft_idx(i) = i - pft_frc(i) = 1.0_r8 - end do - pft_frc(numpft) = 100._r8 - sum(pft_frc(0:numpft-1)) - @assertEqual( 100.0_r8, sum(pft_frc) ) - all_veg_l = .true. - call mkpftInit( zero_out_l, all_veg_l ) - @assertTrue( use_input_pft ) - @assertTrue( presc_cover ) - - end subroutine test_runmkpftInitPftORideAll - - @Test - subroutine test_runmkpftInitPFTOrideWarnNoCrop(this) - class(TestMkPFT), intent(inout) :: this - logical :: zero_out_l, all_veg_l - - zero_out_l = .false. - numpft = maxpft - pft_idx(0) = 1 - pft_frc(0) = 100._r8 - all_veg_l = .true. - call mkpftInit( zero_out_l, all_veg_l ) - @assertTrue( use_input_pft ) - @assertTrue( presc_cover ) - - end subroutine test_runmkpftInitPFTOrideWarnNoCrop - - @Test - subroutine test_runmkpftInitPFTOrideWarnNoNatVeg(this) - class(TestMkPFT), intent(inout) :: this - logical :: zero_out_l, all_veg_l - - zero_out_l = .false. - numpft = maxpft - pft_idx(0) = c3cropindex - pft_frc(0) = 100._r8 - all_veg_l = .true. - call mkpftInit( zero_out_l, all_veg_l ) - @assertTrue( use_input_pft ) - @assertTrue( presc_cover ) - - end subroutine test_runmkpftInitPFTOrideWarnNoNatVeg - - @Test - subroutine test_runmkpftInitBadZeroNInput(this) - class(TestMkPFT), intent(inout) :: this - logical :: zero_out_l, all_veg_l - - zero_out_l = .true. - numpft = maxpft - pft_idx(0) = numstdpft+1 - pft_frc(0) = 100._r8 - all_veg_l = .true. - call mkpftInit( zero_out_l, all_veg_l ) - @assertExceptionRaised( "ABORTED:" ) - - end subroutine test_runmkpftInitBadZeroNInput - - @Test - subroutine test_runmkpftInitBadAllVeg(this) - class(TestMkPFT), intent(inout) :: this - logical :: zero_out_l, all_veg_l - - zero_out_l = .false. - all_veg_l = .true. - call mkpftInit( zero_out_l, all_veg_l ) - @assertExceptionRaised( "ABORTED:" ) - - end subroutine test_runmkpftInitBadAllVeg - - @Test - subroutine test_runmkpftInitBadNotSum(this) - class(TestMkPFT), intent(inout) :: this - logical :: zero_out_l, all_veg_l - - zero_out_l = .false. - all_veg_l = .true. - numpft = maxpft - pft_idx(0) = numstdpft+1 - pft_frc(0) = 99._r8 - call mkpftInit( zero_out_l, all_veg_l ) - @assertExceptionRaised( "ABORTED:" ) - - end subroutine test_runmkpftInitBadNotSum - - @Test - subroutine test_runmkpftInitBadPFTOutRange(this) - class(TestMkPFT), intent(inout) :: this - logical :: zero_out_l, all_veg_l - - zero_out_l = .false. - all_veg_l = .true. - numpft = numstdpft - pft_idx(0) = numstdpft+1 - pft_frc(0) = 100._r8 - call mkpftInit( zero_out_l, all_veg_l ) - @assertExceptionRaised( "ABORTED:" ) - - end subroutine test_runmkpftInitBadPFTOutRange - - @Test - subroutine test_runmkpftInitBadPFTBadVals(this) - class(TestMkPFT), intent(inout) :: this - logical :: zero_out_l, all_veg_l - - zero_out_l = .false. - all_veg_l = .true. - numpft = maxpft - pft_idx(0:1) = (/ numstdpft+1, numstdpft+2 /) - pft_frc(0:1) = (/ 101._r8, -1._r8 /) - call mkpftInit( zero_out_l, all_veg_l ) - @assertExceptionRaised( "ABORTED:" ) - - end subroutine test_runmkpftInitBadPFTBadVals - - @Test - subroutine test_runmkpftInitBadnumpft(this) - class(TestMkPFT), intent(inout) :: this - logical :: zero_out_l, all_veg_l - - zero_out_l = .false. - all_veg_l = .true. - numpft = 79 - call mkpftInit( zero_out_l, all_veg_l ) - @assertExceptionRaised( "ABORTED:" ) - - end subroutine test_runmkpftInitBadnumpft - - @Test - subroutine test_runmkpftInitBadFrcNotIdx(this) - class(TestMkPFT), intent(inout) :: this - logical :: zero_out_l, all_veg_l - - zero_out_l = .false. - all_veg_l = .true. - numpft = maxpft - pft_idx(0) = numstdpft+1 - pft_frc(0:1) = (/ 99._r8, 1._r8 /) - call mkpftInit( zero_out_l, all_veg_l ) - @assertExceptionRaised( "ABORTED:" ) - - end subroutine test_runmkpftInitBadFrcNotIdx - - @Test - subroutine test_runmkpftInitBadIdxTwice(this) - class(TestMkPFT), intent(inout) :: this - logical :: zero_out_l, all_veg_l - - zero_out_l = .false. - all_veg_l = .true. - numpft = maxpft - pft_idx(0:1) = (/ 17, 17 /) - pft_frc(0:1) = (/ 99._r8, 1._r8 /) - call mkpftInit( zero_out_l, all_veg_l ) - @assertExceptionRaised( "ABORTED:" ) - - end subroutine test_runmkpftInitBadIdxTwice - - @Test - subroutine test_runmkpftInitBadFrcAfterZero(this) - class(TestMkPFT), intent(inout) :: this - logical :: zero_out_l, all_veg_l - - zero_out_l = .false. - numpft = maxpft - all_veg_l = .true. - pft_idx(0:2) = (/ 17, -1, 18 /) - pft_frc(0:2) = (/ 99._r8, 0.0_r8, 1._r8 /) - call mkpftInit( zero_out_l, all_veg_l ) - @assertExceptionRaised( "ABORTED:" ) - end subroutine test_runmkpftInitBadFrcAfterZero - - -end module test_pftInit diff --git a/tools/mksurfdata_map/src/test/mkpftmod_test/test_pft_oride.pf b/tools/mksurfdata_map/src/test/mkpftmod_test/test_pft_oride.pf deleted file mode 100644 index bc9cda88de..0000000000 --- a/tools/mksurfdata_map/src/test/mkpftmod_test/test_pft_oride.pf +++ /dev/null @@ -1,127 +0,0 @@ -module test_pft_oride - - ! Tests of mkpftMod: pft_override functions - - use funit - - use shr_kind_mod, only : r8 => shr_kind_r8 - use mkpftMod - use mkvarctl, only : numpft - use mkvarpar, only : numstdpft - use mkpftConstantsMod, only : c3cropindex, c3irrcropindex - - implicit none - save - - @TestCase - type, extends(TestCase) :: TestPFTORide - type(pft_oride) :: pftoverride - contains - procedure :: setUp - procedure :: tearDown - end type TestPFTORide - - logical :: zero_out, all_veg_l - -contains - - subroutine setUp(this) - class(TestPFTORide), intent(inout) :: this - - pft_idx(:) = -1 - pft_frc(:) = 0.0_r8 - zero_out = .false. - numpft = numstdpft - all_veg_l = .false. - call mkpftInit( zero_out, all_veg_l ) - this%pftoverride = pft_oride( ) - end subroutine setUp - - subroutine tearDown(this) - class(TestPFTORide), intent(inout) :: this - - call this%pftoverride%Clean() - - end subroutine tearDown - - @Test - subroutine test_runmkpftZero(this) - class(TestPFTORide), intent(inout) :: this - - zero_out = .true. - all_veg_l = .false. - call mkpftInit( zero_out, all_veg_l ) - call this%pftoverride%InitZeroOut() - @assertEqual( 0.0_r8, this%pftoverride%crop ) - @assertEqual( 0.0_r8, this%pftoverride%natveg ) - @assertEqual( 100.0_r8, sum(this%pftoverride%cft)) - @assertEqual( 100.0_r8, sum(this%pftoverride%natpft)) - - end subroutine test_runmkpftZero - - @Test - subroutine test_runSetpft(this) - class(TestPFTORide), intent(inout) :: this - integer, parameter :: pftidx = 1 - - pft_idx(0) = pftidx - pft_frc(0) = 100.0_r8 - zero_out = .false. - all_veg_l = .true. - call mkpftInit( zero_out, all_veg_l ) - call this%pftoverride%InitAllPFTIndex() - @assertEqual( 0.0_r8, this%pftoverride%crop ) - @assertEqual( 100.0_r8, this%pftoverride%natveg ) - @assertEqual( 100.0_r8, sum(this%pftoverride%cft) ) - @assertEqual( 100.0_r8, sum(this%pftoverride%natpft) ) - @assertEqual( 100.0_r8, this%pftoverride%natpft(pftidx) ) - - end subroutine test_runSetpft - - @Test - subroutine test_runSetCrop(this) - class(TestPFTORide), intent(inout) :: this - integer :: cftidx - - cftidx = c3cropindex - pft_idx(0) = cftidx - pft_frc(0) = 100.0_r8 - zero_out = .false. - all_veg_l = .true. - call mkpftInit( zero_out, all_veg_l ) - call this%pftoverride%InitAllPFTIndex() - @assertEqual( 100.0_r8, this%pftoverride%crop ) - @assertEqual( 0.0_r8, this%pftoverride%natveg ) - @assertEqual( 100.0_r8, sum(this%pftoverride%cft) ) - @assertEqual( 100.0_r8, sum(this%pftoverride%natpft) ) - @assertEqual( 100.0_r8, this%pftoverride%cft(numpft-cftidx) ) - - end subroutine test_runSetCrop - - @Test - subroutine test_runSetMix(this) - class(TestPFTORide), intent(inout) :: this - integer :: cftidx, cftidx2, pftidx2 - integer, parameter :: pftidx = 1 - - zero_out = .false. - pftidx2 = c3cropindex-1 - cftidx = c3cropindex - cftidx2 = c3irrcropindex - pft_idx(0:3) = (/ pftidx, pftidx2, cftidx, cftidx2 /) - pft_frc(0:3) = (/ 25.0_r8, 25.0_r8, 25.0_r8, 25.0_r8 /) - all_veg_l = .true. - call mkpftInit( zero_out, all_veg_l ) - call this%pftoverride%InitAllPFTIndex() - @assertEqual( 50.0_r8, this%pftoverride%crop ) - @assertEqual( 50.0_r8, this%pftoverride%natveg ) - @assertEqual( 100.0_r8, sum(this%pftoverride%cft) ) - @assertEqual( 100.0_r8, sum(this%pftoverride%natpft) ) - @assertEqual( 50.0_r8, this%pftoverride%natpft(pftidx) ) - @assertEqual( 50.0_r8, this%pftoverride%natpft(pftidx2) ) - @assertEqual( 50.0_r8, this%pftoverride%cft(1) ) - @assertEqual( 50.0_r8, this%pftoverride%cft(2) ) - - end subroutine test_runSetMix - -end module test_pft_oride diff --git a/tools/mksurfdata_map/src/test/mkpftmod_test/test_pftrun.pf b/tools/mksurfdata_map/src/test/mkpftmod_test/test_pftrun.pf deleted file mode 100644 index 77c8f0e623..0000000000 --- a/tools/mksurfdata_map/src/test/mkpftmod_test/test_pftrun.pf +++ /dev/null @@ -1,204 +0,0 @@ -module test_pftrun - - ! Tests of mkpftMod: pft_override functions - - use funit - - use shr_kind_mod, only : r8 => shr_kind_r8 - use mkpftMod - use mkvarctl, only: numpft - use mkvarpar, only: numstdpft - use mkpftConstantsMod, only: maxpft, c3cropindex, c3irrcropindex - use mkpctPftTypeMod , only : pct_pft_type - use mkdomainMod , only : domain_type, for_test_create_domain, domain_clean - - implicit none - save - - @TestCase - type, extends(TestCase) :: TestMkPFTRun - character(len=12) :: mapfname - character(len=12) :: fpft - type(domain_type) :: ldomain - integer :: ndiag - real(r8), allocatable :: expected(:) - real(r8) :: expected_cft(2) - real(r8) :: expected_pft(0:14) - type(pct_pft_type), allocatable :: pctnatpft(:) ! % of grid cell that is nat veg, and breakdown into PFTs - real(r8), allocatable :: pctlnd_pft(:) ! PFT data: % of gridcell for PFTs - type(pct_pft_type), allocatable :: pctcft(:) ! % of grid cell that is crop, and breakdown into CFTs - contains - procedure :: setUp - procedure :: tearDown - end type TestMkPFTRun - -contains - - subroutine setUp(this) - class(TestMkPFTRun), intent(inout) :: this - integer :: ns_o - - numpft = numstdpft - pft_idx(0:maxpft) = -1 - pft_frc(0:maxpft) = 0.0_r8 - this%ndiag = 6 - this%mapfname = "none" - this%fpft = "none" - call for_test_create_domain( this%ldomain ) - ns_o = this%ldomain%ns - allocate( this%pctnatpft(ns_o) ) - allocate( this%pctlnd_pft(ns_o) ) - allocate( this%pctcft(ns_o) ) - allocate( this%expected(ns_o) ) - this%expected = 0.0_r8 - this%expected_cft = 0.0_r8 - this%expected_pft = 0.0_r8 - end subroutine setUp - - subroutine tearDown(this) - class(TestMkPFTRun), intent(inout) :: this - - deallocate( this%pctnatpft ) - deallocate( this%pctlnd_pft ) - deallocate( this%pctcft ) - deallocate( this%expected ) - call domain_clean( this%ldomain ) - - end subroutine tearDown - - @Test - subroutine test_runmkpftZero(this) - class(TestMkPFTRun), intent(inout) :: this - logical :: zero_out, all_veg_l - integer :: n - - zero_out = .true. - all_veg_l = .false. - call mkpftInit( zero_out, all_veg_l ) - @assertTrue( use_input_pft ) - @assertTrue( presc_cover ) - call mkpft(this%ldomain, this%mapfname, this%fpft, this%ndiag, & - pctlnd_o=this%pctlnd_pft, pctnatpft_o=this%pctnatpft, pctcft_o=this%pctcft) - this%expected = 100.0_r8 - @assertEqual( this%expected, this%pctlnd_pft ) - do n = 1, this%ldomain%ns - @assertEqual( this%pctnatpft(n)%get_pct_l2g(), 0.0_r8 ) - @assertEqual( this%pctcft(n)%get_pct_l2g(), 0.0_r8 ) - this%expected_pft = 0.0_r8 - this%expected_pft(0) = 100.0_r8 - this%expected_cft = 0.0_r8 - this%expected_cft(1) = 100.0_r8 - @assertEqual( this%pctnatpft(n)%get_pct_p2l(), this%expected_pft ) - @assertEqual( this%pctcft(n)%get_pct_p2l(), this%expected_cft ) - end do - - end subroutine test_runmkpftZero - - @Test - subroutine test_runmkpftPftORide(this) - class(TestMkPFTRun), intent(inout) :: this - logical :: zero_out, all_veg_l - integer :: n - integer, parameter :: pftidx = 1 - - zero_out = .false. - all_veg_l = .true. - pft_idx(0) = pftidx - pft_frc(0) = 100._r8 - call mkpftInit( zero_out, all_veg_l ) - @assertTrue( use_input_pft ) - @assertTrue( presc_cover ) - call mkpft(this%ldomain, this%mapfname, this%fpft, this%ndiag, & - pctlnd_o=this%pctlnd_pft, pctnatpft_o=this%pctnatpft, pctcft_o=this%pctcft) - this%expected = 100.0_r8 - @assertEqual( this%expected, this%pctlnd_pft ) - do n = 1, this%ldomain%ns - @assertEqual( this%pctnatpft(n)%get_pct_l2g(), 100.0_r8 ) - @assertEqual( this%pctcft(n)%get_pct_l2g(), 0.0_r8 ) - this%expected_pft = 0.0_r8 - this%expected_pft(pftidx) = 100.0_r8 - this%expected_cft = 0.0_r8 - this%expected_cft(1) = 100.0_r8 - @assertEqual( this%pctnatpft(n)%get_pct_p2l(), this%expected_pft ) - @assertEqual( this%pctcft(n)%get_pct_p2l(), this%expected_cft ) - end do - - end subroutine test_runmkpftPftORide - - - @Test - subroutine test_runmkpftPftORideWCrop(this) - use mkvarpar, only: numstdpft, numstdcft - class(TestMkPFTRun), intent(inout) :: this - logical :: zero_out, all_veg_l - integer :: n - integer :: cftidx - integer, parameter :: pftidx = 1 - - cftidx = c3cropindex - zero_out = .false. - all_veg_l = .true. - @assertLessThan( pftidx, numstdpft-numstdcft+1 ) - @assertGreaterThan( cftidx, numstdpft-numstdcft ) - pft_idx(0:1) = (/ pftidx, cftidx /) - pft_frc(0:1) = (/ 50.0_r8, 50.0_r8 /) - call mkpftInit( zero_out, all_veg_l ) - @assertTrue( use_input_pft ) - @assertTrue( presc_cover ) - call mkpft(this%ldomain, this%mapfname, this%fpft, this%ndiag, & - pctlnd_o=this%pctlnd_pft, pctnatpft_o=this%pctnatpft, pctcft_o=this%pctcft) - this%expected = 100.0_r8 - @assertEqual( this%expected, this%pctlnd_pft ) - do n = 1, this%ldomain%ns - @assertEqual( this%pctnatpft(n)%get_pct_l2g(), 50.0_r8 ) - @assertEqual( this%pctcft(n)%get_pct_l2g(), 50.0_r8 ) - this%expected_pft = 0.0_r8 - this%expected_pft(pftidx) = 100.0_r8 - this%expected_cft = 0.0_r8 - this%expected_cft(numstdpft-cftidx) = 100.0_r8 - @assertEqual( this%pctnatpft(n)%get_pct_p2l(), this%expected_pft ) - @assertEqual( this%pctcft(n)%get_pct_p2l(), this%expected_cft ) - end do - - end subroutine test_runmkpftPftORideWCrop - - @Test - subroutine test_runmkpft4PftORideWCrop(this) - use mkvarpar, only: numstdpft, numstdcft - class(TestMkPFTRun), intent(inout) :: this - logical :: zero_out, all_veg_l - integer :: n - integer :: cftidx, cftidx2 - integer, parameter :: pftidx = 1, pftidx2 = 2 - - cftidx = c3cropindex - cftidx2 = c3irrcropindex - zero_out = .false. - all_veg_l = .true. - @assertLessThan( pftidx, numstdpft-numstdcft+1 ) - @assertLessThan( pftidx2, numstdpft-numstdcft+1 ) - @assertGreaterThan( cftidx, numstdpft-numstdcft ) - @assertGreaterThan( cftidx2, numstdpft-numstdcft ) - pft_idx(0:3) = (/ pftidx, pftidx2, cftidx, cftidx2 /) - pft_frc(0:3) = (/ 25.0_r8, 25.0_r8, 25.0_r8, 25.0_r8 /) - call mkpftInit( zero_out, all_veg_l ) - @assertTrue( use_input_pft ) - @assertTrue( presc_cover ) - call mkpft(this%ldomain, this%mapfname, this%fpft, this%ndiag, & - pctlnd_o=this%pctlnd_pft, pctnatpft_o=this%pctnatpft, pctcft_o=this%pctcft) - this%expected = 100.0_r8 - @assertEqual( this%expected, this%pctlnd_pft ) - do n = 1, this%ldomain%ns - @assertEqual( this%pctnatpft(n)%get_pct_l2g(), 50.0_r8 ) - @assertEqual( this%pctcft(n)%get_pct_l2g(), 50.0_r8 ) - this%expected_pft = 0.0_r8 - this%expected_pft(pftidx) = 50.0_r8 - this%expected_pft(pftidx2) = 50.0_r8 - this%expected_cft = 50.0_r8 - @assertEqual( this%pctnatpft(n)%get_pct_p2l(), this%expected_pft ) - @assertEqual( this%pctcft(n)%get_pct_p2l(), this%expected_cft ) - end do - - end subroutine test_runmkpft4PftORideWCrop - -end module test_pftrun diff --git a/tools/mksurfdata_map/src/test/mksoilUtils_test/CMakeLists.txt b/tools/mksurfdata_map/src/test/mksoilUtils_test/CMakeLists.txt deleted file mode 100644 index 4d94b8114b..0000000000 --- a/tools/mksurfdata_map/src/test/mksoilUtils_test/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -set (pfunit_sources - test_dominant_soil_color.pf) - -create_pFUnit_test(mksoilUtils test_mksoilUtils_exe - "${pfunit_sources}" "") - -target_link_libraries(test_mksoilUtils_exe mksurfdat) \ No newline at end of file diff --git a/tools/mksurfdata_map/src/test/mksoilUtils_test/test_dominant_soil_color.pf b/tools/mksurfdata_map/src/test/mksoilUtils_test/test_dominant_soil_color.pf deleted file mode 100644 index 011f20d70c..0000000000 --- a/tools/mksurfdata_map/src/test/mksoilUtils_test/test_dominant_soil_color.pf +++ /dev/null @@ -1,140 +0,0 @@ -module test_dominant_soil_color - - ! Tests of mksoilUtilsMod: dominant_soil_color - - use funit - use mksoilUtilsMod - use shr_kind_mod , only : r8 => shr_kind_r8 - use mkgridmapMod, only : gridmap_type, gridmap_clean, for_test_create_gridmap - - implicit none - - @TestCase - type, extends(TestCase) :: tdsc - type(gridmap_type) :: gridmap - contains - procedure :: setUp - procedure :: tearDown - procedure :: createGridmap1dst - end type tdsc - - real(r8), parameter :: tol = 1.e-13_r8 - -contains - - subroutine setUp(this) - class(tdsc), intent(inout) :: this - end subroutine setUp - - subroutine tearDown(this) - class(tdsc), intent(inout) :: this - call gridmap_clean(this%gridmap) - end subroutine tearDown - - subroutine createGridmap1dst(this, wovr) - ! Create this%gridmap with a single destination point - class(tdsc), intent(inout) :: this - real(r8), intent(in) :: wovr(:) ! overlap weights - - integer :: i - integer :: npts - integer :: src_indx(size(wovr)) - integer :: dst_indx(size(wovr)) - - dst_indx(:) = 1 - npts = size(wovr) - src_indx(:) = [(i, i = 1, npts)] - - call for_test_create_gridmap(this%gridmap, na = npts, nb = 1, ns = npts, & - src_indx = src_indx, dst_indx = dst_indx, wovr = wovr) - end subroutine createGridmap1dst - - @Test - subroutine equalWeights(this) - ! Four inputs with equal weight; two of one class, one of each of two other classes - class(tdsc), intent(inout) :: this - integer :: mask_i(4) - integer :: soil_color_i(4) - integer :: soil_color_o(1) - - call this%createGridmap1dst([0.25_r8, 0.25_r8, 0.25_r8, 0.25_r8]) - mask_i(:) = 1 - soil_color_i(:) = [1, 2, 2, 3] - - call dominant_soil_color(this%gridmap, mask_i, soil_color_i, 20, soil_color_o) - - @assertEqual(2, soil_color_o(1)) - end subroutine equalWeights - - @Test - subroutine inequalWeights(this) - ! Four inputs with inequal weight - class(tdsc), intent(inout) :: this - integer :: mask_i(4) - integer :: soil_color_i(4) - integer :: soil_color_o(1) - - call this%createGridmap1dst([0.5_r8, 0.2_r8, 0.2_r8, 0.1_r8]) - mask_i(:) = 1 - soil_color_i(:) = [3, 1, 1, 2] - - call dominant_soil_color(this%gridmap, mask_i, soil_color_i, 20, soil_color_o) - - @assertEqual(3, soil_color_o(1)) - end subroutine inequalWeights - - @Test - subroutine noColor(this) - ! No color in input - class(tdsc), intent(inout) :: this - integer :: mask_i(4) - integer :: soil_color_i(4) - integer :: soil_color_o(1) - - call this%createGridmap1dst([0.25_r8, 0.25_r8, 0.25_r8, 0.25_r8]) - ! Some points are inside the mask with color = 0, other points are outside the mask - mask_i(:) = [1, 0, 0, 1] - soil_color_i(:) = [0, 1, 1, 0] - - call dominant_soil_color(this%gridmap, mask_i, soil_color_i, 20, soil_color_o) - - @assertEqual(15, soil_color_o(1)) - end subroutine noColor - - @Test - subroutine noColorInFirstPoints(this) - ! No color in the first points, but a color in the last point - class(tdsc), intent(inout) :: this - integer :: mask_i(4) - integer :: soil_color_i(4) - integer :: soil_color_o(1) - - call this%createGridmap1dst([0.25_r8, 0.25_r8, 0.25_r8, 0.25_r8]) - ! Some points are inside the mask with color = 0, other points are outside the mask - mask_i(:) = 1 - soil_color_i(:) = [0, 0, 0, 1] - - call dominant_soil_color(this%gridmap, mask_i, soil_color_i, 20, soil_color_o) - - @assertEqual(1, soil_color_o(1)) - end subroutine noColorInFirstPoints - - @Test - subroutine noColorInLastPoints(this) - ! No color in the last points, but a color in the first point - class(tdsc), intent(inout) :: this - integer :: mask_i(4) - integer :: soil_color_i(4) - integer :: soil_color_o(1) - - call this%createGridmap1dst([0.25_r8, 0.25_r8, 0.25_r8, 0.25_r8]) - ! Some points are inside the mask with color = 0, other points are outside the mask - mask_i(:) = 1 - soil_color_i(:) = [1, 0, 0, 0] - - call dominant_soil_color(this%gridmap, mask_i, soil_color_i, 20, soil_color_o) - - @assertEqual(1, soil_color_o(1)) - end subroutine noColorInLastPoints - -end module test_dominant_soil_color diff --git a/tools/mksurfdata_map/src/unit_test_stubs/abort.F90 b/tools/mksurfdata_map/src/unit_test_stubs/abort.F90 deleted file mode 100644 index 8f56fc82fc..0000000000 --- a/tools/mksurfdata_map/src/unit_test_stubs/abort.F90 +++ /dev/null @@ -1,25 +0,0 @@ -subroutine abort() - ! Replacement for abort that throws a pfunit exception rather than aborting - ! - ! This can be used to test expected errors (i.e., failure testing). - ! - ! If this occurs within a pFUnit-based test: - ! - ! - If you have code like: - ! - ! @assertExceptionRaised("ABORTED:") - ! - ! - If you don't have - ! - ! @assertExceptionRaised - ! - ! or - ! - ! call assertExceptionRaised - ! - ! then this will result in the given pFUnit test failing. - use funit, only : throw - implicit none - - call throw("ABORTED:") -end subroutine abort diff --git a/tools/mksurfdata_map/src/unit_test_stubs/mkncdio.F90 b/tools/mksurfdata_map/src/unit_test_stubs/mkncdio.F90 deleted file mode 100644 index 1bf6a8afdf..0000000000 --- a/tools/mksurfdata_map/src/unit_test_stubs/mkncdio.F90 +++ /dev/null @@ -1,223 +0,0 @@ -module mkncdio - ! Stub of mkncdio for unit testing. This is enough to get other modules to compile, but - ! it doesn't do anything useful. - - use shr_kind_mod, only : r8 => shr_kind_r8 - - implicit none - private - - public :: nf_open - public :: nf_close - public :: nf_strerror - public :: nf_inq_dimid - public :: nf_inq_dimname - public :: nf_inq_dimlen - public :: nf_inq_varid - public :: nf_inq_varndims - public :: nf_inq_vardimid - public :: nf_get_var_double - public :: nf_get_var_int - public :: nf_get_vara_double - public :: nf_get_att_double - public :: ncd_defvar - public :: ncd_def_spatial_var - - public :: get_dim_lengths - - public :: check_ret - public :: convert_latlon - - interface nf_get_var_double - module procedure nf_get_var_double_1d - module procedure nf_get_var_double_2d - end interface nf_get_var_double - - interface nf_get_vara_double - module procedure nf_get_vara_double_2d - end interface nf_get_vara_double - - integer, parameter, public :: nf_nowrite = 0 - integer, parameter, public :: nf_noerr = 0 - integer, parameter, public :: nf_max_name = 64 - -contains - -!----------------------------------------------------------------------- - subroutine ncd_defvar(ncid, varname, xtype, & - dim1name, dim2name, & - long_name, units ) -! - implicit none - integer , intent(in) :: ncid ! input unit - character(len=*), intent(in) :: varname ! variable name - integer , intent(in) :: xtype ! external type - character(len=*), intent(in), optional :: dim1name ! dimension name - character(len=*), intent(in), optional :: dim2name ! dimension name - character(len=*), intent(in), optional :: long_name ! attribute - character(len=*), intent(in), optional :: units ! attribute -! - end subroutine ncd_defvar - - !----------------------------------------------------------------------- - subroutine ncd_def_spatial_var(ncid, varname, xtype, long_name, units, lev1name, lev2name) - integer , intent(in) :: ncid ! input unit - character(len=*) , intent(in) :: varname ! variable name - integer , intent(in) :: xtype ! external type - character(len=*) , intent(in) :: long_name ! attribute - character(len=*) , intent(in) :: units ! attribute - character(len=*) , optional, intent(in) :: lev1name ! name of first level (or time) dimension - character(len=*) , optional, intent(in) :: lev2name ! name of second level (or time) dimension - end subroutine ncd_def_spatial_var - - subroutine get_dim_lengths(ncid, varname, ndims, dim_lengths) - integer , intent(in) :: ncid ! netcdf id of an open netcdf file - character(len=*), intent(in) :: varname ! name of variable of interest - integer , intent(out):: ndims ! number of dimensions of variable - integer , intent(out):: dim_lengths(:) ! lengths of dimensions of variable - - dim_lengths = 0 - end subroutine get_dim_lengths - - integer function nf_open(filename, mode, ncid) - character(len=*), intent(in) :: filename - integer, intent(in) :: mode - integer, intent(out) :: ncid - - ncid = 0 - nf_open = 0 - end function nf_open - - integer function nf_close(ncid) - integer, intent(in) :: ncid - - nf_close = 0 - end function nf_close - - function nf_strerror(rcode) - character(len=16) :: nf_strerror - integer, intent(in) :: rcode - - nf_strerror = 'N/A' - end function nf_strerror - - integer function nf_inq_dimid(ncid, dimname, did) - integer, intent(in) :: ncid - character(len=*), intent(in) :: dimname - integer, intent(out) :: did - - did = 0 - nf_inq_dimid = 0 - end function nf_inq_dimid - - integer function nf_inq_dimname(ncid, dimid, dimname) - integer, intent(in) :: ncid - integer, intent(in) :: dimid - character(len=*), intent(out) :: dimname - - dimname = 'none' - nf_inq_dimname = 0 - end function nf_inq_dimname - - integer function nf_inq_dimlen(ncid, did, dimlen) - integer, intent(in) :: ncid - integer, intent(in) :: did - integer, intent(out) :: dimlen - - dimlen = 0 - nf_inq_dimlen = 0 - end function nf_inq_dimlen - - integer function nf_inq_varid(ncid, varname, vid) - integer, intent(in) :: ncid - character(len=*), intent(in) :: varname - integer, intent(out) :: vid - - vid = 0 - nf_inq_varid = 0 - end function nf_inq_varid - - integer function nf_inq_varndims(ncid, varid, ndims) - integer, intent(in) :: ncid - integer, intent(in) :: varid - integer, intent(out) :: ndims - - ndims = 0 - nf_inq_varndims = 0 - end function nf_inq_varndims - - integer function nf_inq_vardimid(ncid, varid, dimids) - integer, intent(in) :: ncid - integer, intent(in) :: varid - integer, intent(out) :: dimids(:) - - dimids(:) = 0 - nf_inq_vardimid = 0 - end function nf_inq_vardimid - - integer function nf_get_var_double_1d(ncid, vid, data) - integer, intent(in) :: ncid - integer, intent(in) :: vid - real(r8), intent(out) :: data(:) - - data(:) = 0._r8 - nf_get_var_double_1d = 0 - end function nf_get_var_double_1d - - integer function nf_get_var_double_2d(ncid, vid, data) - integer, intent(in) :: ncid - integer, intent(in) :: vid - real(r8), intent(out) :: data(:,:) - - data(:,:) = 0._r8 - nf_get_var_double_2d = 0 - end function nf_get_var_double_2d - - integer function nf_get_var_int(ncid, vid, data) - integer, intent(in) :: ncid - integer, intent(in) :: vid - integer, intent(out) :: data(:) - - data(:) = 0 - nf_get_var_int = 0 - end function nf_get_var_int - - integer function nf_get_vara_double_2d(ncid, varid, starts, counts, data) - integer, intent(in) :: ncid - integer, intent(in) :: varid - integer, intent(in) :: starts(:) - integer, intent(in) :: counts(:) - real(r8), intent(out) :: data(:,:) - - data(:,:) = 0._r8 - nf_get_vara_double_2d = 0 - end function nf_get_vara_double_2d - - integer function nf_get_att_double(ncid, varid, attname, attval) - integer, intent(in) :: ncid - integer, intent(in) :: varid - character(len=*), intent(in) :: attname - real(r8), intent(out) :: attval - - attval = 0._r8 - nf_get_att_double = 0 - end function nf_get_att_double - - subroutine check_ret(ret, calling, varexists) - integer, intent(in) :: ret - character(len=*), intent(in) :: calling - logical, intent(out), optional :: varexists - - if (present(varexists)) then - varexists = .true. - end if - end subroutine check_ret - - subroutine convert_latlon(ncid, varname, data) - integer, intent(in) :: ncid - character(len=*), intent(in) :: varname - real(r8), intent(inout) :: data(:) - - end subroutine convert_latlon - -end module mkncdio diff --git a/tools/mksurfdata_map/unit_testers/Filepath b/tools/mksurfdata_map/unit_testers/Filepath deleted file mode 100644 index f5228276ec..0000000000 --- a/tools/mksurfdata_map/unit_testers/Filepath +++ /dev/null @@ -1,2 +0,0 @@ -. -../src diff --git a/tools/mksurfdata_map/unit_testers/Makefile b/tools/mksurfdata_map/unit_testers/Makefile deleted file mode 100644 index 7260c828d8..0000000000 --- a/tools/mksurfdata_map/unit_testers/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# Makefile for mksurfdata_map unit testing - -EXENAME = ../test_mksurfdata_map - -# Set optimization off by default -ifeq ($(OPT),$(null)) - OPT := FALSE -endif - -include ../src/Makefile.common \ No newline at end of file diff --git a/tools/mksurfdata_map/unit_testers/README b/tools/mksurfdata_map/unit_testers/README deleted file mode 100644 index 8620c3cc6d..0000000000 --- a/tools/mksurfdata_map/unit_testers/README +++ /dev/null @@ -1,6 +0,0 @@ -This directory contains source code for building unit tests for -mksurfdata_map - -test_mod.F90 was copied from -https://svn-ccsm-models.cgd.ucar.edu/csm_share/trunk/unit_testers/test_mod.F90 - diff --git a/tools/mksurfdata_map/unit_testers/Srcfiles b/tools/mksurfdata_map/unit_testers/Srcfiles deleted file mode 100644 index 3ee42a79bb..0000000000 --- a/tools/mksurfdata_map/unit_testers/Srcfiles +++ /dev/null @@ -1,32 +0,0 @@ -test_mksurfdata_map.F90 -test_mkdomainMod.F90 -test_mkindexmapMod.F90 -test_mkgridmapMod.F90 -test_mkchecksMod.F90 -test_mkurbanparMod.F90 -test_mkutilsMod.F90 -test_mkharvest.F90 -test_mkncdio.F90 -test_mod.F90 -mkindexmapMod.F90 -mkchecksMod.F90 -mkharvestMod.F90 -mkurbanparMod.F90 -mkdiagnosticsMod.F90 -mkurbanparCommonMod.F90 -mkutilsMod.F90 -mkdomainMod.F90 -mkvarpar.F90 -mkgridmapMod.F90 -mkncdio.F90 -mkvarctl.F90 -nanMod.F90 -fileutils.F90 -shr_const_mod.F90 -shr_kind_mod.F90 -shr_sys_mod.F90 -shr_log_mod.F90 -shr_string_mod.F90 -shr_timer_mod.F90 -shr_file_mod.F90 - diff --git a/tools/mksurfdata_map/unit_testers/test_mkchecksMod.F90 b/tools/mksurfdata_map/unit_testers/test_mkchecksMod.F90 deleted file mode 100644 index edec7643e5..0000000000 --- a/tools/mksurfdata_map/unit_testers/test_mkchecksMod.F90 +++ /dev/null @@ -1,101 +0,0 @@ -module test_mkchecksMod -! Module for testing mkchecksMod - - use mkchecksMod - use test_mod - use shr_kind_mod, only : r8 => shr_kind_r8 - - implicit none - private - - public :: test_min_bad - public :: test_max_bad - - character(len=*), parameter :: modname = 'test_mkchecksMod' - -contains - -!------------------------------------------------------------------------------ - subroutine test_min_bad - - implicit none - - character(len=128) :: testname - logical :: test_result - - character(len=*), parameter :: subname = 'test_min_bad' - - ! Tests for r8 - - testname = 'r8 - pass' - test_result = min_bad((/1._r8,2._r8,3._r8/), 0._r8, 'testvar') - call test_is(test_result .eqv. .false., modname//' -- '//subname//' -- '//trim(testname)) - - testname = 'r8 - pass on border' - test_result = min_bad((/1._r8,2._r8,3._r8/), 1._r8, 'testvar') - call test_is(test_result .eqv. .false., modname//' -- '//subname//' -- '//trim(testname)) - - ! Note that we expect output to stdout from the following test that indicates an error - testname = 'r8 - fail' - test_result = min_bad((/1._r8,2._r8,3._r8/), 1.5_r8, 'testvar') - call test_is(test_result .eqv. .true., modname//' -- '//subname//' -- '//trim(testname)) - - ! Tests for int - - testname = 'int - pass' - test_result = min_bad((/1,2,3/), 0, 'testvar') - call test_is(test_result .eqv. .false., modname//' -- '//subname//' -- '//trim(testname)) - - testname = 'int - pass on border' - test_result = min_bad((/1,2,3/), 1, 'testvar') - call test_is(test_result .eqv. .false., modname//' -- '//subname//' -- '//trim(testname)) - - ! Note that we expect output to stdout from the following test that indicates an error - testname = 'int - fail' - test_result = min_bad((/1,2,3/), 2, 'testvar') - call test_is(test_result .eqv. .true., modname//' -- '//subname//' -- '//trim(testname)) - - end subroutine test_min_bad - -!------------------------------------------------------------------------------ - subroutine test_max_bad - - implicit none - - character(len=128) :: testname - logical :: test_result - - character(len=*), parameter :: subname = 'test_max_bad' - - ! Tests for r8 - - testname = 'r8 - pass' - test_result = max_bad((/1._r8,2._r8,3._r8/), 4._r8, 'testvar') - call test_is(test_result .eqv. .false., modname//' -- '//subname//' -- '//trim(testname)) - - testname = 'r8 - pass on border' - test_result = max_bad((/1._r8,2._r8,3._r8/), 3._r8, 'testvar') - call test_is(test_result .eqv. .false., modname//' -- '//subname//' -- '//trim(testname)) - - ! Note that we expect output to stdout from the following test that indicates an error - testname = 'r8 - fail' - test_result = max_bad((/1._r8,2._r8,3._r8/), 2.5_r8, 'testvar') - call test_is(test_result .eqv. .true., modname//' -- '//subname//' -- '//trim(testname)) - - ! Tests for int - - testname = 'int - pass' - test_result = max_bad((/1,2,3/), 4, 'testvar') - call test_is(test_result .eqv. .false., modname//' -- '//subname//' -- '//trim(testname)) - - testname = 'int - pass on border' - test_result = max_bad((/1,2,3/), 3, 'testvar') - call test_is(test_result .eqv. .false., modname//' -- '//subname//' -- '//trim(testname)) - - ! Note that we expect output to stdout from the following test that indicates an error - testname = 'int - fail' - test_result = max_bad((/1,2,3/), 2, 'testvar') - call test_is(test_result .eqv. .true., modname//' -- '//subname//' -- '//trim(testname)) - - end subroutine test_max_bad -end module test_mkchecksMod diff --git a/tools/mksurfdata_map/unit_testers/test_mkdomainMod.F90 b/tools/mksurfdata_map/unit_testers/test_mkdomainMod.F90 deleted file mode 100644 index 56a37e7f28..0000000000 --- a/tools/mksurfdata_map/unit_testers/test_mkdomainMod.F90 +++ /dev/null @@ -1,95 +0,0 @@ -module test_mkdomainMod -! Module for testing mkindexmapMod - - use mkdomainMod - use test_mod - use shr_kind_mod, only : r8 => shr_kind_r8 - - implicit none - private - - public :: test_domain_read_dims - - character(len=*), parameter :: modname = 'test_mkdomainMod' - -contains - -!------------------------------------------------------------------------------ - subroutine test_domain_read_dims - - use mkncdio - - implicit none - - type(domain_type) :: domain - integer :: ncid - character(len=128) :: testname - - integer :: ni_t, nj_t, ns_t - logical :: is_2d_t - - character(len=*), parameter :: subname = 'test_domain_read_dims' - - testname = 'lon' - call check_ret(nf_open('unit_testers/inputs/test_domain_read_dims__lon.nc', 0, ncid), subname) - ni_t = 2 - nj_t = 3 - ns_t = 6 - is_2d_t = .true. - call domain_read_dims(domain, ncid) - call check_results_2d - - testname = 'lsmlon' - call check_ret(nf_open('unit_testers/inputs/test_domain_read_dims__lsmlon.nc', 0, ncid), subname) - ni_t = 3 - nj_t = 4 - ns_t = 12 - is_2d_t = .true. - call domain_read_dims(domain, ncid) - call check_results_2d - - ! When we have both 'lon' and 'ni', should use 'ni' - testname = 'lon_and_ni' - call check_ret(nf_open('unit_testers/inputs/test_domain_read_dims__lon_and_ni.nc', 0, ncid), subname) - ni_t = 4 - nj_t = 5 - ns_t = 20 - is_2d_t = .true. - call domain_read_dims(domain, ncid) - call check_results_2d - - ! test 1-d - testname = 'num_pixels' - call check_ret(nf_open('unit_testers/inputs/test_domain_read_dims__num_pixels.nc', 0, ncid), subname) - ns_t = 17 - is_2d_t = .false. - call domain_read_dims(domain, ncid) - call check_results_1d - - ! When we have both 2-d and 1-d info, should use 2-d info - testname = 'lon_and_num_pixels' - call check_ret(nf_open('unit_testers/inputs/test_domain_read_dims__lon_and_num_pixels.nc', 0, ncid), subname) - ni_t = 2 - nj_t = 3 - ns_t = 6 - is_2d_t = .true. - call domain_read_dims(domain, ncid) - call check_results_2d - - contains - subroutine check_results_1d - call test_is(domain%ns, ns_t, modname//' -- '//subname//' -- '//trim(testname)//' -- ns') - call test_is((domain%is_2d .eqv. is_2d_t), modname//' -- '//subname//' -- '//trim(testname)//' -- is_2d') - end subroutine check_results_1d - - subroutine check_results_2d - call test_is(domain%ns, ns_t, modname//' -- '//subname//' -- '//trim(testname)//' -- ns') - call test_is(domain%ni, ni_t, modname//' -- '//subname//' -- '//trim(testname)//' -- ni') - call test_is(domain%nj, nj_t, modname//' -- '//subname//' -- '//trim(testname)//' -- nj') - call test_is((domain%is_2d .eqv. is_2d_t), modname//' -- '//subname//' -- '//trim(testname)//' -- is_2d') - end subroutine check_results_2d - end subroutine test_domain_read_dims -end module test_mkdomainMod - - - diff --git a/tools/mksurfdata_map/unit_testers/test_mkgridmapMod.F90 b/tools/mksurfdata_map/unit_testers/test_mkgridmapMod.F90 deleted file mode 100644 index 77fb3ffd9a..0000000000 --- a/tools/mksurfdata_map/unit_testers/test_mkgridmapMod.F90 +++ /dev/null @@ -1,476 +0,0 @@ -module test_mkgridmapMod - ! Module for testing mkgridmapMod - - use mkgridmapMod - use test_mod - use shr_kind_mod, only : r8 => shr_kind_r8 - - implicit none - private - - public :: test_gridmap_areastddev - public :: test_gridmap_areaave_no_srcmask - public :: test_gridmap_areaave_srcmask - - character(len=*), parameter :: modname = 'test_mkgridmapMod' - -contains - - !------------------------------------------------------------------------------ - subroutine test_gridmap_areaave_no_srcmask - - implicit none - - type(gridmap_type) :: gridmap - character(len=128) :: testname - - real(r8), allocatable :: src_array(:) - real(r8), allocatable :: dst_array(:) - real(r8), allocatable :: dst_array_t(:) - - real(r8), parameter :: nodata = -1._r8 - real(r8), parameter :: eps = 1.e-13_r8 - - character(len=*), parameter :: subname = 'test_gridmap_areaave_no_srcmask' - - ! Note about the gridmaps for the tests here: - ! For most tests here, the test arrays are: (1) simple case, (2) the main case to - ! test, (3) simple case. Thus, the main case in question is #2 of 3, and we're always - ! basically just testing one scenario in each call to the subroutine (rather than - ! doing a bunch of tests at once, which could make setting up the test arrays more - ! error-prone). - - ! Set up a gridmap with 0 weight of overlap on dest #2 - gridmap%na = 4 - gridmap%nb = 3 - gridmap%ns = 4 - allocate(gridmap%src_indx(gridmap%ns), & - gridmap%dst_indx(gridmap%ns), & - gridmap%wovr (gridmap%ns), & - gridmap%frac_dst(gridmap%nb)) - gridmap%src_indx = (/1,2,3,4/) - gridmap%dst_indx = (/1,1,3,3/) - gridmap%wovr = (/0.75_r8,0.25_r8, & ! weights of sources 1:2 on dest 1 - 0.25_r8,0.75_r8/) ! weights of sources 3:4 on test 3 - gridmap%frac_dst = (/1.0, 0.0, 1.0/) - gridmap%set = 'gridmap_IsSet' - allocate(src_array (gridmap%na), & - dst_array (gridmap%nb), & - dst_array_t(gridmap%nb)) - testname = 'no overlap' - src_array = (/0.1_r8,0.2_r8,0.3_r8,0.4_r8/) - dst_array_t = (/0.125_r8, nodata, 0.375_r8/) - call gridmap_areaave_no_srcmask(gridmap, src_array, dst_array, nodata) - call test_close(dst_array, dst_array_t, eps, modname//' -- '//subname//' -- '//trim(testname)) - deallocate(gridmap%src_indx, gridmap%dst_indx, gridmap%wovr, gridmap%frac_dst) - deallocate(src_array, dst_array, dst_array_t) - - ! Set up a gridmap with a single point overlapping dest #2 - gridmap%na = 5 - gridmap%nb = 3 - gridmap%ns = 5 - allocate(gridmap%src_indx(gridmap%ns), & - gridmap%dst_indx(gridmap%ns), & - gridmap%wovr (gridmap%ns), & - gridmap%frac_dst(gridmap%nb)) - gridmap%src_indx = (/1,2,3,4,5/) - gridmap%dst_indx = (/1,1,2,3,3/) - gridmap%wovr = (/0.75_r8,0.25_r8, & ! weights of sources 1:2 on dest 1 - 1.0_r8, & ! weight of source 3 on dest 2 - 0.25_r8,0.75_r8/) ! weights of sources 4:5 on test 3 - gridmap%frac_dst = (/1.0, 1.0, 1.0/) - gridmap%set = 'gridmap_IsSet' - allocate(src_array (gridmap%na), & - dst_array (gridmap%nb), & - dst_array_t(gridmap%nb)) - testname = 'single overlap' - src_array = (/0.1_r8,0.2_r8,0.5_r8,0.3_r8,0.4_r8/) - dst_array_t = (/0.125_r8, 0.5_r8, 0.375_r8/) - call gridmap_areaave_no_srcmask(gridmap, src_array, dst_array, nodata) - call test_close(dst_array, dst_array_t, eps, modname//' -- '//subname//' -- '//trim(testname)) - - ! Now change the overlap point to have weight=0 - testname = 'single overlap with 0 weight' - gridmap%wovr(3) = 0.0_r8 - gridmap%frac_dst(2) = 0.0_r8 - dst_array_t(2) = nodata - call gridmap_areaave_no_srcmask(gridmap, src_array, dst_array, nodata) - call test_close(dst_array, dst_array_t, eps, modname//' -- '//subname//' -- '//trim(testname)) - - deallocate(gridmap%src_indx, gridmap%dst_indx, gridmap%wovr, gridmap%frac_dst) - deallocate(src_array, dst_array, dst_array_t) - - ! Set up a gridmap for the remaining tests - ! This gridmap will have 3 src cells, 9 dest cells, and: - ! src 1: just overlaps with dst 1 - ! src 2: overlaps with dst 1 & dst 2 - ! src 3..7: just overlaps with dst 2 - ! src 8: overlaps with dst 2 & dst 3 - ! src 9: just overlaps with dst 3 - gridmap%na = 9 - gridmap%nb = 3 - gridmap%ns = 11 - allocate(gridmap%src_indx(gridmap%ns), & - gridmap%dst_indx(gridmap%ns), & - gridmap%wovr (gridmap%ns), & - gridmap%frac_dst(gridmap%nb)) - gridmap%src_indx = (/1,2,2,3,4,5,6,7,8,8,9/) - gridmap%dst_indx = (/1,1,2,2,2,2,2,2,2,3,3/) - gridmap%wovr = (/0.75_r8,0.25_r8, & ! weights of sources 1:2 on dest 1 - 0.05_r8,0.05_r8,0.1_r8,0.3_r8,0.2_r8,0.15_r8,0.15_r8, & ! weights of sources 2:8 on dest 2 - 0.25_r8,0.75_r8/) ! weights of sources 8:9 on test 3 - gridmap%frac_dst = (/1.0_r8, 1.0_r8, 1.0_r8/) - gridmap%set = 'gridmap_IsSet' - allocate(src_array (gridmap%na), & - dst_array (gridmap%nb), & - dst_array_t(gridmap%nb)) - - - testname='multiple overlaps, all the same value' - src_array = (/0.1_r8, 0.5_r8, 0.5_r8, 0.5_r8, 0.5_r8, 0.5_r8, 0.5_r8, 0.5_r8, 0.6_r8/) - dst_array_t = (/0.2_r8, 0.5_r8, 0.575_r8/) - call gridmap_areaave_no_srcmask(gridmap, src_array, dst_array, nodata) - call test_close(dst_array, dst_array_t, eps, modname//' -- '//subname//' -- '//trim(testname)) - - testname='multiple overlaps, different values' - src_array = (/0.1_r8, 0.2_r8, 0.3_r8, 0.7_r8, 0.5_r8, 1.5_r8, 0.5_r8, 1.7_r8, 1.8_r8/) - dst_array_t = (/0.125_r8, 0.875_r8, 1.775_r8/) - call gridmap_areaave_no_srcmask(gridmap, src_array, dst_array, nodata) - call test_close(dst_array, dst_array_t, eps, modname//' -- '//subname//' -- '//trim(testname)) - - ! dividing the weights by 2 shouldn't affect the mean - testname='weights divided by 2' - gridmap%wovr(:) = gridmap%wovr(:) / 2.0_r8 - gridmap%frac_dst(:) = gridmap%frac_dst(:) / 2.0_r8 - src_array = (/0.1_r8, 0.2_r8, 0.3_r8, 0.7_r8, 0.5_r8, 1.5_r8, 0.5_r8, 1.7_r8, 1.8_r8/) - dst_array_t = (/0.125_r8, 0.875_r8, 1.775_r8/) - call gridmap_areaave_no_srcmask(gridmap, src_array, dst_array, nodata) - call test_close(dst_array, dst_array_t, eps, modname//' -- '//subname//' -- '//trim(testname)) - ! restore wovr & frac_dst - gridmap%wovr(:) = gridmap%wovr(:) * 2.0_r8 - gridmap%frac_dst(:) = gridmap%frac_dst(:) * 2.0_r8 - - ! using frac_dst > 1 should be okay - testname='frac_dst > 1' - gridmap%wovr(:) = gridmap%wovr(:) * 2.0_r8 - gridmap%frac_dst(:) = gridmap%frac_dst(:) * 2.0_r8 - src_array = (/0.1_r8, 0.2_r8, 0.3_r8, 0.7_r8, 0.5_r8, 1.5_r8, 0.5_r8, 1.7_r8, 1.8_r8/) - dst_array_t = (/0.125_r8, 0.875_r8, 1.775_r8/) - call gridmap_areaave_no_srcmask(gridmap, src_array, dst_array, nodata) - call test_close(dst_array, dst_array_t, eps, modname//' -- '//subname//' -- '//trim(testname)) - ! restore wovr & frac_dst - gridmap%wovr(:) = gridmap%wovr(:) / 2.0_r8 - gridmap%frac_dst(:) = gridmap%frac_dst(:) / 2.0_r8 - - deallocate(src_array, dst_array, dst_array_t) - - end subroutine test_gridmap_areaave_no_srcmask - - !------------------------------------------------------------------------------ - subroutine test_gridmap_areaave_srcmask - - implicit none - - type(gridmap_type) :: gridmap - character(len=128) :: testname - - real(r8), allocatable :: src_array(:) - integer , allocatable :: mask_src(:) - real(r8), allocatable :: dst_array(:) - real(r8), allocatable :: dst_array_t(:) - - real(r8), parameter :: nodata = -1._r8 - real(r8), parameter :: eps = 1.e-13_r8 - - character(len=*), parameter :: subname = 'test_gridmap_areaave_srcmask' - - ! Note about the gridmaps for the tests here: - ! For most tests here, the test arrays are: (1) simple case, (2) the main case to - ! test, (3) simple case. Thus, the main case in question is #2 of 3, and we're always - ! basically just testing one scenario in each call to the subroutine (rather than - ! doing a bunch of tests at once, which could make setting up the test arrays more - ! error-prone). - - ! Set up a gridmap with 0 weight of overlap on dest #2 - gridmap%na = 4 - gridmap%nb = 3 - gridmap%ns = 4 - allocate(gridmap%src_indx(gridmap%ns), & - gridmap%dst_indx(gridmap%ns), & - gridmap%wovr (gridmap%ns), & - gridmap%frac_dst(gridmap%nb)) - gridmap%src_indx = (/1,2,3,4/) - gridmap%dst_indx = (/1,1,3,3/) - gridmap%wovr = (/0.75_r8,0.25_r8, & ! weights of sources 1:2 on dest 1 - 0.25_r8,0.75_r8/) ! weights of sources 3:4 on test 3 - gridmap%frac_dst = (/1.0, 0.0, 1.0/) - gridmap%set = 'gridmap_IsSet' - allocate(src_array (gridmap%na), & - mask_src (gridmap%na), & - dst_array (gridmap%nb), & - dst_array_t(gridmap%nb)) - testname = 'no overlap' - src_array = (/0.1_r8,0.2_r8,0.3_r8,0.4_r8/) - mask_src(:) = 1 - dst_array_t = (/0.125_r8, nodata, 0.375_r8/) - call gridmap_areaave_srcmask(gridmap, src_array, dst_array, nodata, mask_src=mask_src, frac_dst=gridmap%frac_dst) - call test_close(dst_array, dst_array_t, eps, modname//' -- '//subname//' -- '//trim(testname)) - deallocate(gridmap%src_indx, gridmap%dst_indx, gridmap%wovr, gridmap%frac_dst) - deallocate(src_array, mask_src, dst_array, dst_array_t) - - ! Set up a gridmap with a single point overlapping dest #2 - gridmap%na = 5 - gridmap%nb = 3 - gridmap%ns = 5 - allocate(gridmap%src_indx(gridmap%ns), & - gridmap%dst_indx(gridmap%ns), & - gridmap%wovr (gridmap%ns), & - gridmap%frac_dst(gridmap%nb)) - gridmap%src_indx = (/1,2,3,4,5/) - gridmap%dst_indx = (/1,1,2,3,3/) - gridmap%wovr = (/0.75_r8,0.25_r8, & ! weights of sources 1:2 on dest 1 - 1.0_r8, & ! weight of source 3 on dest 2 - 0.25_r8,0.75_r8/) ! weights of sources 4:5 on test 3 - gridmap%frac_dst = (/1.0, 1.0, 1.0/) - gridmap%set = 'gridmap_IsSet' - allocate(src_array (gridmap%na), & - mask_src (gridmap%na), & - dst_array (gridmap%nb), & - dst_array_t(gridmap%nb)) - testname = 'single overlap' - src_array = (/0.1_r8,0.2_r8,0.5_r8,0.3_r8,0.4_r8/) - mask_src(:) = 1.0_r8 - dst_array_t = (/0.125_r8, 0.5_r8, 0.375_r8/) - call gridmap_areaave_srcmask(gridmap, src_array, dst_array, nodata, mask_src=mask_src, frac_dst=gridmap%frac_dst) - call test_close(dst_array, dst_array_t, eps, modname//' -- '//subname//' -- '//trim(testname)) - - ! Now change the overlap point to have src_mask=0 - testname = 'single overlap with 0 src_mask' - mask_src(3) = 0.0_r8 - dst_array_t(2) = nodata - call gridmap_areaave_srcmask(gridmap, src_array, dst_array, nodata, mask_src=mask_src, frac_dst=gridmap%frac_dst) - call test_close(dst_array, dst_array_t, eps, modname//' -- '//subname//' -- '//trim(testname)) - - deallocate(gridmap%src_indx, gridmap%dst_indx, gridmap%wovr, gridmap%frac_dst) - deallocate(src_array, mask_src, dst_array, dst_array_t) - - ! Set up a gridmap for the remaining tests - ! This gridmap will have 3 src cells, 9 dest cells, and: - ! src 1: just overlaps with dst 1 - ! src 2: overlaps with dst 1 & dst 2 - ! src 3..7: just overlaps with dst 2 - ! src 8: overlaps with dst 2 & dst 3 - ! src 9: just overlaps with dst 3 - gridmap%na = 9 - gridmap%nb = 3 - gridmap%ns = 11 - allocate(gridmap%src_indx(gridmap%ns), & - gridmap%dst_indx(gridmap%ns), & - gridmap%wovr (gridmap%ns), & - gridmap%frac_dst(gridmap%nb)) - gridmap%src_indx = (/1,2,2,3,4,5,6,7,8,8,9/) - gridmap%dst_indx = (/1,1,2,2,2,2,2,2,2,3,3/) - gridmap%wovr = (/0.75_r8,0.25_r8, & ! weights of sources 1:2 on dest 1 - 0.05_r8,0.05_r8,0.1_r8,0.3_r8,0.2_r8,0.15_r8,0.15_r8, & ! weights of sources 2:8 on dest 2 - 0.25_r8,0.75_r8/) ! weights of sources 8:9 on test 3 - gridmap%frac_dst = (/1.0_r8, 1.0_r8, 1.0_r8/) - gridmap%set = 'gridmap_IsSet' - allocate(src_array (gridmap%na), & - mask_src (gridmap%na), & - dst_array (gridmap%nb), & - dst_array_t(gridmap%nb)) - - - testname='multiple overlaps, all the same value' - src_array = (/0.1_r8, 0.5_r8, 0.5_r8, 0.5_r8, 0.5_r8, 0.5_r8, 0.5_r8, 0.5_r8, 0.6_r8/) - mask_src(:) = 1.0_r8 - dst_array_t = (/0.2_r8, 0.5_r8, 0.575_r8/) - call gridmap_areaave_srcmask(gridmap, src_array, dst_array, nodata, mask_src=mask_src, frac_dst=gridmap%frac_dst) - call test_close(dst_array, dst_array_t, eps, modname//' -- '//subname//' -- '//trim(testname)) - - testname='multiple overlaps, different values' - src_array = (/0.1_r8, 0.2_r8, 0.3_r8, 0.7_r8, 0.5_r8, 1.5_r8, 0.5_r8, 1.7_r8, 1.8_r8/) - mask_src(:) = 1.0_r8 - dst_array_t = (/0.125_r8, 0.875_r8, 1.775_r8/) - call gridmap_areaave_srcmask(gridmap, src_array, dst_array, nodata, mask_src=mask_src, frac_dst=gridmap%frac_dst) - call test_close(dst_array, dst_array_t, eps, modname//' -- '//subname//' -- '//trim(testname)) - - testname='multiple overlaps, different values, srcmask' - src_array = (/0.1_r8, 0.2_r8, 0.3_r8, 0.7_r8, 0.5_r8, 1.5_r8, 0.5_r8, 1.7_r8, 1.8_r8/) - mask_src(:) = (/1.0_r8, 1.0_r8, 0.0_r8, 0.5_r8, 1.0_r8, 0.5_r8, 0.0_r8, 1.0_r8, 1.0_r8/) - dst_array_t = (/0.125_r8, 0.923076923076923_r8, 1.775_r8/) - call gridmap_areaave_srcmask(gridmap, src_array, dst_array, nodata, mask_src=mask_src, frac_dst=gridmap%frac_dst) - call test_close(dst_array, dst_array_t, eps, modname//' -- '//subname//' -- '//trim(testname)) - - ! dividing the weights by 2 and dividing mask_src by a constant shouldn't affect the mean - testname='weights divided by 2' - gridmap%wovr(:) = gridmap%wovr(:) / 2.0_r8 - gridmap%frac_dst(:) = gridmap%frac_dst(:) / 2.0_r8 - src_array = (/0.1_r8, 0.2_r8, 0.3_r8, 0.7_r8, 0.5_r8, 1.5_r8, 0.5_r8, 1.7_r8, 1.8_r8/) - mask_src(:) = 0.25_r8 - dst_array_t = (/0.125_r8, 0.875_r8, 1.775_r8/) - call gridmap_areaave_srcmask(gridmap, src_array, dst_array, nodata, mask_src=mask_src, frac_dst=gridmap%frac_dst) - call test_close(dst_array, dst_array_t, eps, modname//' -- '//subname//' -- '//trim(testname)) - ! restore wovr & frac_dst - gridmap%wovr(:) = gridmap%wovr(:) * 2.0_r8 - gridmap%frac_dst(:) = gridmap%frac_dst(:) * 2.0_r8 - - ! using frac_dst > 1 should be okay - testname='frac_dst > 1' - gridmap%wovr(:) = gridmap%wovr(:) * 2.0_r8 - gridmap%frac_dst(:) = gridmap%frac_dst(:) * 2.0_r8 - src_array = (/0.1_r8, 0.2_r8, 0.3_r8, 0.7_r8, 0.5_r8, 1.5_r8, 0.5_r8, 1.7_r8, 1.8_r8/) - mask_src(:) = 0.25_r8 - dst_array_t = (/0.125_r8, 0.875_r8, 1.775_r8/) - call gridmap_areaave_srcmask(gridmap, src_array, dst_array, nodata, mask_src=mask_src, frac_dst=gridmap%frac_dst) - call test_close(dst_array, dst_array_t, eps, modname//' -- '//subname//' -- '//trim(testname)) - ! restore wovr & frac_dst - gridmap%wovr(:) = gridmap%wovr(:) / 2.0_r8 - gridmap%frac_dst(:) = gridmap%frac_dst(:) / 2.0_r8 - - - deallocate(src_array, mask_src, dst_array, dst_array_t) - - end subroutine test_gridmap_areaave_srcmask - - !------------------------------------------------------------------------------ - subroutine test_gridmap_areastddev - - implicit none - - type(gridmap_type) :: gridmap - character(len=128) :: testname - - real(r8), allocatable :: src_array(:) - real(r8), allocatable :: dst_array(:) - real(r8), allocatable :: dst_array_t(:) - - real(r8), parameter :: nodata = -1._r8 - real(r8), parameter :: eps = 1.e-13_r8 - - character(len=*), parameter :: subname = 'test_gridmap_areastddev' - - ! Note about the gridmaps for the tests here: - ! For most tests here, the test arrays are: (1) simple case, (2) the main case to - ! test, (3) simple case. Thus, the main case in question is #2 of 3, and we're always - ! basically just testing one scenario in each call to the subroutine (rather than - ! doing a bunch of tests at once, which could make setting up the test arrays more - ! error-prone). - - ! Set up a gridmap with 0 weight of overlap on dest #2 - gridmap%na = 4 - gridmap%nb = 3 - gridmap%ns = 4 - allocate(gridmap%src_indx(gridmap%ns), & - gridmap%dst_indx(gridmap%ns), & - gridmap%wovr (gridmap%ns), & - gridmap%frac_dst(gridmap%nb)) - gridmap%src_indx = (/1,2,3,4/) - gridmap%dst_indx = (/1,1,3,3/) - gridmap%wovr = (/0.75_r8,0.25_r8, & ! weights of sources 1:2 on dest 1 - 0.25_r8,0.75_r8/) ! weights of sources 3:4 on test 3 - gridmap%frac_dst = (/1.0, 0.0, 1.0/) - gridmap%set = 'gridmap_IsSet' - allocate(src_array (gridmap%na), & - dst_array (gridmap%nb), & - dst_array_t(gridmap%nb)) - testname = 'no overlap' - src_array = (/0.1_r8,0.2_r8,0.3_r8,0.4_r8/) - dst_array_t = (/0.04330127018922193_r8, nodata, 0.04330127018922195_r8/) - call gridmap_areastddev(gridmap, src_array, dst_array, nodata) - call test_close(dst_array, dst_array_t, eps, modname//' -- '//subname//' -- '//trim(testname)) - deallocate(gridmap%src_indx, gridmap%dst_indx, gridmap%wovr, gridmap%frac_dst) - deallocate(src_array, dst_array, dst_array_t) - - ! Set up a gridmap with a single point overlapping dest #2 - gridmap%na = 5 - gridmap%nb = 3 - gridmap%ns = 5 - allocate(gridmap%src_indx(gridmap%ns), & - gridmap%dst_indx(gridmap%ns), & - gridmap%wovr (gridmap%ns), & - gridmap%frac_dst(gridmap%nb)) - gridmap%src_indx = (/1,2,3,4,5/) - gridmap%dst_indx = (/1,1,2,3,3/) - gridmap%wovr = (/0.75_r8,0.25_r8, & ! weights of sources 1:2 on dest 1 - 1.0_r8, & ! weight of source 3 on dest 2 - 0.25_r8,0.75_r8/) ! weights of sources 4:5 on test 3 - gridmap%frac_dst = (/1.0, 1.0, 1.0/) - gridmap%set = 'gridmap_IsSet' - allocate(src_array (gridmap%na), & - dst_array (gridmap%nb), & - dst_array_t(gridmap%nb)) - testname = 'single overlap' - src_array = (/0.1_r8,0.2_r8,0.5_r8,0.3_r8,0.4_r8/) - dst_array_t = (/0.04330127018922193_r8, 0.0_r8, 0.04330127018922195_r8/) - call gridmap_areastddev(gridmap, src_array, dst_array, nodata) - call test_close(dst_array, dst_array_t, eps, modname//' -- '//subname//' -- '//trim(testname)) - deallocate(gridmap%src_indx, gridmap%dst_indx, gridmap%wovr, gridmap%frac_dst) - deallocate(src_array, dst_array, dst_array_t) - - ! Set up a gridmap for the remaining tests - ! This gridmap will have 3 src cells, 9 dest cells, and: - ! src 1: just overlaps with dst 1 - ! src 2: overlaps with dst 1 & dst 2 - ! src 3..7: just overlaps with dst 2 - ! src 8: overlaps with dst 2 & dst 3 - ! src 9: just overlaps with dst 3 - gridmap%na = 9 - gridmap%nb = 3 - gridmap%ns = 11 - allocate(gridmap%src_indx(gridmap%ns), & - gridmap%dst_indx(gridmap%ns), & - gridmap%wovr (gridmap%ns), & - gridmap%frac_dst(gridmap%nb)) - gridmap%src_indx = (/1,2,2,3,4,5,6,7,8,8,9/) - gridmap%dst_indx = (/1,1,2,2,2,2,2,2,2,3,3/) - gridmap%wovr = (/0.75_r8,0.25_r8, & ! weights of sources 1:2 on dest 1 - 0.05_r8,0.05_r8,0.1_r8,0.3_r8,0.2_r8,0.15_r8,0.15_r8, & ! weights of sources 2:8 on dest 2 - 0.25_r8,0.75_r8/) ! weights of sources 8:9 on test 3 - gridmap%frac_dst = (/1.0_r8, 1.0_r8, 1.0_r8/) - gridmap%set = 'gridmap_IsSet' - allocate(src_array (gridmap%na), & - dst_array (gridmap%nb), & - dst_array_t(gridmap%nb)) - - - testname='multiple overlaps, all the same value' - src_array = (/0.1_r8, 0.5_r8, 0.5_r8, 0.5_r8, 0.5_r8, 0.5_r8, 0.5_r8, 0.5_r8, 0.6_r8/) - dst_array_t = (/0.1732050807568877_r8, 0.0_r8, 0.04330127018922193_r8/) - call gridmap_areastddev(gridmap, src_array, dst_array, nodata) - call test_close(dst_array, dst_array_t, eps, modname//' -- '//subname//' -- '//trim(testname)) - - testname='multiple overlaps, different values' - src_array = (/0.1_r8, 0.2_r8, 0.3_r8, 0.7_r8, 0.5_r8, 1.5_r8, 0.5_r8, 1.7_r8, 1.8_r8/) - dst_array_t = (/0.04330127018922193_r8, 0.5346727971385864_r8, 0.04330127018922197_r8/) - call gridmap_areastddev(gridmap, src_array, dst_array, nodata) - call test_close(dst_array, dst_array_t, eps, modname//' -- '//subname//' -- '//trim(testname)) - - ! dividing the weights by 2 shouldn't affect the standard deviation - testname='weights divided by 2' - gridmap%wovr(:) = gridmap%wovr(:) / 2.0_r8 - gridmap%frac_dst(:) = gridmap%frac_dst(:) / 2.0_r8 - src_array = (/0.1_r8, 0.2_r8, 0.3_r8, 0.7_r8, 0.5_r8, 1.5_r8, 0.5_r8, 1.7_r8, 1.8_r8/) - dst_array_t = (/0.04330127018922193_r8, 0.5346727971385864_r8, 0.04330127018922197_r8/) - call gridmap_areastddev(gridmap, src_array, dst_array, nodata) - call test_close(dst_array, dst_array_t, eps, modname//' -- '//subname//' -- '//trim(testname)) - ! restore wovr & frac_dst - gridmap%wovr(:) = gridmap%wovr(:) * 2.0_r8 - gridmap%frac_dst(:) = gridmap%frac_dst(:) * 2.0_r8 - - ! using frac_dst > 1 should be okay - testname='frac_dst > 1' - gridmap%wovr(:) = gridmap%wovr(:) * 2.0_r8 - gridmap%frac_dst(:) = gridmap%frac_dst(:) * 2.0_r8 - src_array = (/0.1_r8, 0.2_r8, 0.3_r8, 0.7_r8, 0.5_r8, 1.5_r8, 0.5_r8, 1.7_r8, 1.8_r8/) - dst_array_t = (/0.04330127018922193_r8, 0.5346727971385864_r8, 0.04330127018922197_r8/) - call gridmap_areastddev(gridmap, src_array, dst_array, nodata) - call test_close(dst_array, dst_array_t, eps, modname//' -- '//subname//' -- '//trim(testname)) - ! restore wovr & frac_dst - gridmap%wovr(:) = gridmap%wovr(:) / 2.0_r8 - gridmap%frac_dst(:) = gridmap%frac_dst(:) / 2.0_r8 - - deallocate(src_array, dst_array, dst_array_t) - - end subroutine test_gridmap_areastddev -end module test_mkgridmapMod diff --git a/tools/mksurfdata_map/unit_testers/test_mkharvest.F90 b/tools/mksurfdata_map/unit_testers/test_mkharvest.F90 deleted file mode 100644 index 421af9d620..0000000000 --- a/tools/mksurfdata_map/unit_testers/test_mkharvest.F90 +++ /dev/null @@ -1,316 +0,0 @@ -module test_mkharvest -! Module for testing harvest - - use shr_kind_mod, only : r8 => shr_kind_r8 - use mkharvestMod - use test_mod - - implicit none - private - - public :: test_harvest_init - public :: test_harvest_init_old - public :: test_harvest_data - public :: test_harvest_data_all1D - - character(len=*), parameter :: modname = 'test_harvest' - - character(len=128) :: testname - character(len=128) :: test_prefix - integer, parameter :: ns_o = 4 - -contains - -!------------------------------------------------------------------------------ - subroutine test_harvest_init - - use mkncdio - implicit none - - integer :: ncid - type(harvestDataType) :: harvdata - character(len=128) :: varname - integer :: varid - logical :: varexists - integer :: ifld - character(len=*), parameter :: constfieldname(9) = (/ & - 'CONST_HARVEST_VH1 ', & - 'CONST_HARVEST_VH2 ', & - 'CONST_HARVEST_SH1 ', & - 'CONST_HARVEST_SH2 ', & - 'CONST_HARVEST_SH3 ', & - 'CONST_GRAZING ', & - 'CONST_FERTNITRO_CFT ', & - 'UNREPRESENTED_PFT_LULCC', & - 'UNREPRESENTED_CFT_LULCC' & - /) - character(len=*), parameter :: units(9) = (/ & - 'gC/m2/yr', & - 'gC/m2/yr', & - 'gC/m2/yr', & - 'gC/m2/yr', & - 'gC/m2/yr', & - 'gC/m2/yr', & - 'gN/m2/yr', & - 'unitless', & - 'unitless' & - /) - character(len=*), parameter :: fieldname(9) = (/ & - 'HARVEST_VH1 ', & - 'HARVEST_VH2 ', & - 'HARVEST_SH1 ', & - 'HARVEST_SH2 ', & - 'HARVEST_SH3 ', & - 'GRAZING ', & - 'FERTNITRO_CFT', & - 'PFT_LULCC ', & - 'CFT_LULCC ' & - /) - character(len=*), parameter :: longname(9) = (/ & - 'harvest from primary forest ', & - 'harvest from primary non-forest ', & - 'harvest from secondary mature-forest ', & - 'harvest from secondary young-forest ', & - 'harvest from secondary non-forest ', & - 'grazing of herbacous pfts ', & - 'constant background nitrogen fertilizer for each crop ', & - 'constant background unrepresented PFT LULCC transitions ', & - 'constant background unrepresented crop LULCC transitions' & - /) - character(len=256) :: string - character(len=*), parameter :: filename = 'unit_testers/inputs/harvestfields.nc' - - character(len=*), parameter :: subname = 'test_harvest_init' - integer :: nfields - - testname = 'check harvest_init' - test_prefix = modname//' -- '//subname//' -- '//trim(testname)//' -- ' - ! Open netcdf file that will be used for most tests - call check_ret(nf_open(filename, 0, ncid), subname) - varname = 'GRAZING' - call check_ret(nf_inq_varid(ncid, varname, varid), subname, varexists=varexists) - call test_is(varexists, trim(test_prefix)//'existing var') - call test_is( .not.mkharvest_fieldInBounds( 3 ), trim(test_prefix)//'allfieldsoutofboundsbeforeinit') - - call mkharvest_init( ns_o, 0.0_r8, harvdata, filename ) - call test_is( .not.mkharvest_fieldInBounds( 0 ), trim(test_prefix)//'0 out of bounds') - nfields = mkharvest_numtypes() - call test_is( .not.mkharvest_fieldInBounds( nfields+1), trim(test_prefix)//'10 out of bounds') - - ! make sure can now do getter functions - - do ifld = 1, mkharvest_numtypes() - call test_is(mkharvest_fieldname(ifld,constant=.true.), constfieldname(ifld), trim(test_prefix)//'bad const fieldname') - call test_is(mkharvest_fieldname(ifld), fieldname(ifld), trim(test_prefix)//trim(testname)//'bad fieldname') - call test_is(mkharvest_units(ifld), units(ifld), trim(test_prefix)//'bad units') - call test_is(mkharvest_longname(ifld), longname(ifld), trim(test_prefix)//'bad longname') - end do - call harvdata%clean() - - end subroutine test_harvest_init - - subroutine test_harvest_data_all1D() - implicit none - type(harvestDataType) :: harvdata - integer :: dim2nd(9) - integer :: dsizes(2), nfields, ifld, n, doutsizes(2) - integer :: dims1D(1), dims2D(2) - character(len=*), parameter :: subname = 'test_harvest_data' - character(len=*), parameter :: filename = 'unit_testers/inputs/harvestfields.nc' - integer, parameter :: indices1D(9) = (/ 1, 2, 3, 4, 5, 6, 7, 8, 9 /) - integer, parameter :: indices2D(1) = (/ -1 /) - real(r8), pointer :: data1D(:) - integer, allocatable :: ind1D(:), ind2D(:) - integer, parameter :: ns_i = 15, ns_o = 10 - - testname = 'check harvest_data_all1D' - test_prefix = modname//' -- '//subname//' -- '//trim(testname)//' -- ' - dim2nd = 0 - call mkharvest_init( ns_o, 0.0_r8, harvdata, filename ) - call harvdata%clean() - call harvdata%init( dim2nd, ns_i, ns_o, 0.0_r8 ) - do ifld = 1, mkharvest_numtypes() - call test_is(harvdata%isField1D(ifld), trim(test_prefix)//'field is 1D' ) - call test_is(.not.harvdata%isField2D(ifld), trim(test_prefix)//'field not 2D' ) - end do - nfields = mkharvest_numtypes() - call test_is(harvdata%num1DFields(),nfields,trim(test_prefix)//'num 1D fields') - call test_is(harvdata%num2DFields(),0,trim(test_prefix)//'num 2D fields') - call harvdata%getFieldsIdx( ind1D, ind2D ) - call test_is(ind1D,indices1D,trim(test_prefix)//'1D fields indices') - call test_is(ind2D,indices2D,trim(test_prefix)//'2D fields indices') - dsizes(1) = ns_i - doutsizes(1) = ns_o - do n = 1, harvdata%num1DFields() - call test_is(harvdata%isField1D(indices1D(n)), trim(test_prefix)//'verify field is 1D' ) - data1D => harvdata%get1DFieldPtr( indices1D(n) ) - dims1D = shape(data1D) - call test_is(dims1D,dsizes(:),trim(test_prefix)//'1D field dims') - ! Set data - data1D(:) = real( n, r8 ) - data1D => null() - ! Output data - data1D => harvdata%get1DFieldPtr( indices1D(n), output=.true. ) - dims1D = shape(data1D) - call test_is(dims1D,doutsizes(:),trim(test_prefix)//'1D Output field dims') - ! Set data - data1D(:) = real( n*100, r8 ) - data1D => null() - end do - ! Check that data is set from setting above - do n = 1, harvdata%num1DFields() - data1D => harvdata%get1DFieldPtr( indices1D(n) ) - call test_is(data1D(1),real( n, r8 ), trim(test_prefix)//'field ') - data1D => null() - ! output data - data1D => harvdata%get1DFieldPtr( indices1D(n), output=.true. ) - call test_is(data1D(1),real( n*100, r8 ), trim(test_prefix)//'field ') - data1D => null() - end do - call harvdata%clean() - end subroutine test_harvest_data_all1D - -!------------------------------------------------------------------------------ - - subroutine test_harvest_data() - implicit none - type(harvestDataType) :: harvdata - integer :: dsizes(2), nfields, ifld, n, doutsizes(2) - integer :: dims1D(1), dims2D(2) - character(len=*), parameter :: subname = 'test_harvest_data' - character(len=*), parameter :: filename = 'unit_testers/inputs/harvestfields.nc' - integer, parameter :: indices1D(6) = (/ 1, 2, 3, 4, 5, 6 /) - integer, parameter :: indices2D(3) = (/ 7, 8, 9 /) - integer, parameter :: dim2nd(3) = (/ 64, 15, 64 /) - character(len=10) :: dimnames(3) = (/ "cft", "natpft", "cft" /) - real(r8), pointer :: data1D(:) - real(r8), pointer :: data2D(:,:) - integer, allocatable :: ind1D(:), ind2D(:) - integer, parameter :: ns_i = 4, ns_o = 20 - - testname = 'check harvest_data' - test_prefix = modname//' -- '//subname//' -- '//trim(testname)//' -- ' - call mkharvest_init( ns_o, 0.0_r8, harvdata, filename ) - call harvdata%getFieldsIdx( ind1D, ind2D ) - call test_is(ind1D,indices1D,trim(test_prefix)//'1D fields indices') - call test_is(ind2D,indices2D,trim(test_prefix)//'2D fields indices') - call test_is(harvdata%num1DFields(),size(indices1D),trim(test_prefix)//'num 1D fields') - call test_is(harvdata%num2DFields(),size(indices2D),trim(test_prefix)//'num 2D fields') - do n = 1, harvdata%num1DFields() - ifld = ind1D(n) - call test_is(harvdata%isField1D(ifld), trim(test_prefix)//'field is 1D' ) - call test_is(.not.harvdata%isField2D(ifld), trim(test_prefix)//'field not 2D' ) - end do - do n = 1, harvdata%num2DFields() - ifld = ind2D(n) - call test_is(.not.harvdata%isField1D(ifld), trim(test_prefix)//'field is not 1D' ) - call test_is(harvdata%isField2D(ifld), trim(test_prefix)//'field is 2D' ) - end do - dsizes(1) = ns_i - doutsizes(1) = ns_o - do n = 1, harvdata%num1DFields() - call test_is(harvdata%isField1D(indices1D(n)), trim(test_prefix)//'verify field is 1D' ) - data1D => harvdata%get1DFieldPtr( indices1D(n) ) - dims1D = shape(data1D) - call test_is(dims1D,dsizes(:),trim(test_prefix)//'1D field dims') - call test_is(harvdata%getFieldsDim(indices1D(n)),"none",trim(test_prefix)//'1D field dimname') - data1D => null() - end do - do n = 1, harvdata%num2DFields() - dsizes(2) = dim2nd(n) - call test_is(harvdata%isField2D(indices2D(n)), trim(test_prefix)//'verify field is 2D' ) - data2D => harvdata%get2DFieldPtr( indices2D(n) ) - dims2D = shape(data2D) - call test_is(dims2D,dsizes(:),trim(test_prefix)//'2D field dims') - call test_is(harvdata%getFieldsDim(indices2D(n)),dimnames(n),trim(test_prefix)//'1D field dimname') - data2D => null() - end do - call harvdata%clean() - end subroutine test_harvest_data - - -!------------------------------------------------------------------------------ - subroutine test_harvest_init_old - - use mkncdio - implicit none - - type(harvestDataType) :: harvdata - character(len=128) :: testname - integer :: ncid - character(len=128) :: varname - integer :: varid - logical :: varexists - integer, parameter :: ns_o = 4 - integer :: ifld - - character(len=*), parameter :: filename = 'unit_testers/inputs/harvestfieldsold.nc' - - character(len=*), parameter :: subname = 'test_harvest_init' - character(len=*), parameter :: constfieldname(9) = (/ & - 'CONST_HARVEST_VH1 ', & - 'CONST_HARVEST_VH2 ', & - 'CONST_HARVEST_SH1 ', & - 'CONST_HARVEST_SH2 ', & - 'CONST_HARVEST_SH3 ', & - 'CONST_GRAZING ', & - 'CONST_FERTNITRO_CFT ', & - 'UNREPRESENTED_PFT_LULCC', & - 'UNREPRESENTED_CFT_LULCC' & - /) - character(len=*), parameter :: units(9) = (/ & - 'unitless ', & - 'unitless ', & - 'unitless ', & - 'unitless ', & - 'unitless ', & - 'unitless ', & - 'not_read_in', & - 'not_read_in', & - 'not_read_in' & - /) - character(len=*), parameter :: fieldname(9) = (/ & - 'HARVEST_VH1 ', & - 'HARVEST_VH2 ', & - 'HARVEST_SH1 ', & - 'HARVEST_SH2 ', & - 'HARVEST_SH3 ', & - 'GRAZING ', & - 'FERTNITRO_CFT', & - 'PFT_LULCC ', & - 'CFT_LULCC ' & - /) - character(len=*), parameter :: longname(9) = (/ & - 'harvest from primary forest ', & - 'harvest from primary non-forest ', & - 'harvest from secondary mature-forest', & - 'harvest from secondary young-forest ', & - 'harvest from secondary non-forest ', & - 'grazing of herbacous pfts ', & - 'FERTNITRO_CFT (zeroed out) ', & - 'PFT_LULCC (zeroed out) ', & - 'CFT_LULCC (zeroed out) ' & - /) - character(len=256) :: string - testname = 'check harvest_init_old' - ! Open netcdf file that will be used for most tests - call check_ret(nf_open(filename, 0, ncid), subname) - varname = 'GRAZING' - call check_ret(nf_inq_varid(ncid, varname, varid), subname, varexists=varexists) - call test_is(varexists, modname//' -- '//subname//' -- '//trim(testname)//' -- existing var') - - call mkharvest_init( ns_o, 0.0_r8, harvdata, filename ) - - ! make sure can now do getter functions - - do ifld = 1, mkharvest_numtypes() - call test_is(mkharvest_fieldname(ifld,constant=.true.), constfieldname(ifld), modname//' -- '//subname//' -- '//trim(testname)//' -- bad const fieldname') - call test_is(mkharvest_fieldname(ifld), fieldname(ifld), modname//' -- '//subname//' -- '//trim(testname)//' -- bad fieldname') - call test_is(mkharvest_units(ifld), units(ifld), modname//' -- '//subname//' -- '//trim(testname)//' -- bad units') - call test_is(mkharvest_longname(ifld), longname(ifld), modname//' -- '//subname//' -- '//trim(testname)//' -- bad longname') - end do - call harvdata%clean() - - end subroutine test_harvest_init_old - -end module test_mkharvest diff --git a/tools/mksurfdata_map/unit_testers/test_mkindexmapMod.F90 b/tools/mksurfdata_map/unit_testers/test_mkindexmapMod.F90 deleted file mode 100644 index 709d6dac0c..0000000000 --- a/tools/mksurfdata_map/unit_testers/test_mkindexmapMod.F90 +++ /dev/null @@ -1,573 +0,0 @@ -module test_mkindexmapMod -! Module for testing mkindexmapMod - - use mkindexmapMod - use test_mod - use shr_kind_mod, only : r8 => shr_kind_r8 - - implicit none - private - - public :: test_get_dominant_indices - public :: test_lookup_2d - public :: test_lookup_2d_netcdf - public :: test_which_max - - character(len=*), parameter :: modname = 'test_mkindexmapMod' - -contains - -!------------------------------------------------------------------------------ - subroutine test_get_dominant_indices - - use mkgridmapMod, only : gridmap_type - - implicit none - - type(gridmap_type) :: gridmap - character(len=128) :: testname - - integer, allocatable :: src_array(:) - integer, allocatable :: mask_src(:) - integer, allocatable :: dst_array(:) - integer, allocatable :: dst_array_t(:) - logical, allocatable :: filter(:) - integer :: minval, maxval, nodata - - character(len=*), parameter :: subname = 'test_get_dominant_indices' - - ! Set up a gridmap that will be used for most tests, and allocate corresponding - ! arrays: - ! Note that, for most tests here, the test arrays are: (1) simple case, (2) the main - ! case to test, (3) simple case. Thus, the main case in question is #2 of 3, and - ! we're always basically just testing one scenario in each call to the subroutine - ! (rather than doing a bunch of tests at once, which could make setting up the test - ! arrays more error-prone). - - ! This gridmap will have 3 src cells, 9 dest cells, and: - ! src 1: just overlaps with dst 1 - ! src 2: overlaps with dst 1 & dst 2 - ! src 3..7: just overlaps with dst 2 - ! src 8: overlaps with dst 2 & dst 3 - ! src 9: just overlaps with dst 3 - ! Note: I'm not setting some things that aren't used in get_dominant_indices - gridmap%na = 9 - gridmap%nb = 3 - gridmap%ns = 11 - allocate(gridmap%src_indx(gridmap%ns), & - gridmap%dst_indx(gridmap%ns), & - gridmap%wovr (gridmap%ns)) - gridmap%src_indx = (/1,2,2,3,4,5,6,7,8,8,9/) - gridmap%dst_indx = (/1,1,2,2,2,2,2,2,2,3,3/) - gridmap%wovr = (/0.75,0.25, & ! weights of sources 1:2 on dest 1 - 0.1,0.1,0.1,0.3,0.2,0.2,0.2, & ! weights of sources 2:8 on dest 2 - 0.25,0.75/) ! weights of sources 8:9 on test 3 - allocate(src_array (gridmap%na), & - mask_src (gridmap%na), & - dst_array (gridmap%nb), & - dst_array_t(gridmap%nb), & - filter (gridmap%ns)) - - testname = 'basic test, all unique' - src_array = (/1, 2, 3, 4, 5, 6, 7, 8, 9/) - mask_src(:) = 1 ! same for all the tests - minval = 1 - maxval = 9 - nodata = -1 - ! dst 2 takes its value from src 5 because it has the largest weight: - dst_array_t = (/1, 5, 9/) - call get_dominant_indices(gridmap, src_array, dst_array, minval, maxval, nodata, mask_src=mask_src) - call test_is(dst_array, dst_array_t, modname//' -- '//subname//' -- '//trim(testname)) - - testname = 'basic test, some duplicates' - src_array = (/1, 2, 3, 3, 4, 2, 2, 1, 1/) - minval = 1 - maxval = 4 - nodata = -1 - dst_array_t = (/1, 2, 1/) - call get_dominant_indices(gridmap, src_array, dst_array, minval, maxval, nodata, mask_src=mask_src) - call test_is(dst_array, dst_array_t, modname//' -- '//subname//' -- '//trim(testname)) - - testname = 'minval not 1' - src_array = (/3, 4, 5, 5, 6, 4, 4, 3, 3/) - minval = 3 - maxval = 6 - nodata = -1 - dst_array_t = (/3, 4, 3/) - call get_dominant_indices(gridmap, src_array, dst_array, minval, maxval, nodata, mask_src=mask_src) - call test_is(dst_array, dst_array_t, modname//' -- '//subname//' -- '//trim(testname)) - - testname = 'single non-zero source value' - src_array = (/1, 0, 0, 0, 0, 2, 0, 0, 1/) - minval = 1 - maxval = 2 - nodata = -1 - dst_array_t = (/1, 2, 1/) - call get_dominant_indices(gridmap, src_array, dst_array, minval, maxval, nodata, mask_src=mask_src) - call test_is(dst_array, dst_array_t, modname//' -- '//subname//' -- '//trim(testname)) - - testname = 'single value within given min-max range' - src_array = (/1, 0, 9, 9, 0, 2, 9, 9, 1/) - minval = 1 - maxval = 2 - nodata = -1 - dst_array_t = (/1, 2, 1/) - call get_dominant_indices(gridmap, src_array, dst_array, minval, maxval, nodata, mask_src=mask_src) - call test_is(dst_array, dst_array_t, modname//' -- '//subname//' -- '//trim(testname)) - - testname = 'no valid values' - src_array = (/1, 0, 9, 9, 0, 0, 9, 9, 1/) - minval = 1 - maxval = 2 - nodata = -1 - dst_array_t = (/1, nodata, 1/) - call get_dominant_indices(gridmap, src_array, dst_array, minval, maxval, nodata, mask_src=mask_src) - call test_is(dst_array, dst_array_t, modname//' -- '//subname//' -- '//trim(testname)) - - testname = 'some filters false' - src_array = (/1, 2, 3, 3, 4, 2, 2, 1, 1/) - minval = 1 - maxval = 4 - nodata = -1 - filter = (/.true., .true., & - .false., .true., .true., .true., .false., .true., .true., & - .true., .true./) - dst_array_t = (/1, 4, 1/) - call get_dominant_indices(gridmap, src_array, dst_array, minval, maxval, nodata, filter=filter, mask_src=mask_src) - call test_is(dst_array, dst_array_t, modname//' -- '//subname//' -- '//trim(testname)) - - testname = 'all filters false' - src_array = (/1, 2, 3, 3, 4, 2, 2, 1, 1/) - minval = 1 - maxval = 4 - nodata = -1 - filter = (/.true., .true., & - .false., .false., .false., .false., .false., .false., .false., & - .true., .true./) - dst_array_t = (/1, nodata, 1/) - call get_dominant_indices(gridmap, src_array, dst_array, minval, maxval, nodata, filter=filter, mask_src=mask_src) - call test_is(dst_array, dst_array_t, modname//' -- '//subname//' -- '//trim(testname)) - - ! Modify gridmap weights for the following test - gridmap%wovr = (/0.75,0.25, & ! weights of sources 1:2 on dest 1 - 0.0,0.0,0.0,0.0,0.0,0.0,0.0, & ! weights of sources 2:8 on dest 2 - 0.25,0.75/) ! weights of sources 8:9 on test 3 - testname='all weights 0' - src_array = (/1, 1, 1, 1, 1, 1, 1, 1, 1/) - minval = 1 - maxval = 2 - nodata = -1 - dst_array_t = (/1, nodata, 1/) - call get_dominant_indices(gridmap, src_array, dst_array, minval, maxval, nodata, mask_src=mask_src) - call test_is(dst_array, dst_array_t, modname//' -- '//subname//' -- '//trim(testname)) - - ! Make a new gridmap for the following test; - ! this involves more output cells and a more complex mapping from src to dst - ! This gridmap will have: - ! dst 1: from src 1, 4, 7 - ! dst 2: from src 2, 4, 6 - ! dst 3: from src 1 - ! dst 4: no overlapping src cells - ! dst 5: from src 5, 7, 8 - ! note that src 3 & 9 do not overlap with any dst - deallocate(gridmap%src_indx, gridmap%dst_indx, gridmap%wovr, & - src_array, dst_array, dst_array_t, filter) - gridmap%na = 9 - gridmap%nb = 5 - gridmap%ns = 10 - allocate(gridmap%src_indx(gridmap%ns), & - gridmap%dst_indx(gridmap%ns), & - gridmap%wovr (gridmap%ns)) - gridmap%src_indx = (/1, 2, 4, 4, 7, 6, 1, 5, 7, 8/) - gridmap%dst_indx = (/1, 2, 1, 2, 1, 2, 3, 5, 5, 5/) - gridmap%wovr = (/1, 1, 2, 2, 1, 3, 1, 2, 2, 3/) - allocate(src_array (gridmap%na), & - dst_array (gridmap%nb), & - dst_array_t(gridmap%nb), & - filter (gridmap%ns)) - - testname = 'more complex gridmap' - ! src index: 1 2 3 4 5 6 7 8 9 - src_array = (/1, 2, 3, 1, 5, 6, 5, 8, 9/) - minval = 1 - maxval = 9 - nodata = -1 - dst_array_t = (/1, 6, 1, nodata, 5/) - call get_dominant_indices(gridmap, src_array, dst_array, minval, maxval, nodata, mask_src=mask_src) - call test_is(dst_array, dst_array_t, modname//' -- '//subname//' -- '//trim(testname)) - - deallocate(gridmap%src_indx, gridmap%dst_indx, gridmap%wovr, & - src_array, dst_array_t, filter) - - end subroutine test_get_dominant_indices -!------------------------------------------------------------------------------ - -!------------------------------------------------------------------------------ - subroutine test_lookup_2d - - implicit none - - character(len=128) :: testname - real(r8), allocatable :: lookup_table(:,:) - logical , allocatable :: valid_entries(:,:) - integer , allocatable :: index1(:), index2(:) - real(r8), allocatable :: data(:), data_t(:) - real(r8) :: fill_val - integer :: nodata - integer :: ierr, ierr_t - - character(len=*), parameter :: subname = 'test_lookup_2d' - - ! Create lookup table for use in most tests - allocate(lookup_table(2,3), valid_entries(2,3)) - lookup_table(1,:) = (/11.,12.,13./) - lookup_table(2,:) = (/21.,22.,23./) - - testname = 'basic test; no nodata or valid_entries' - allocate(index1(5), index2(5), data(5), data_t(5)) - index1 = (/1,2,1,2,2/) - index2 = (/1,2,3,2,3/) - fill_val = -1. - data_t = (/11., 22., 13., 22., 23./) - ierr_t = 0 - call lookup_2d(index1, index2, lookup_table, fill_val, data, ierr) - call check_results - deallocate(index1, index2, data, data_t) - - testname = 'basic test but with index out of range' - allocate(index1(5), index2(5), data(5), data_t(5)) - index1 = (/1,2,3,2,2/) - index2 = (/1,2,1,2,4/) - fill_val = -1. - data_t = (/11._r8, 22._r8, fill_val, 22._r8, fill_val/) - ierr_t = 2 - call lookup_2d(index1, index2, lookup_table, fill_val, data, ierr) - call check_results - deallocate(index1, index2, data, data_t) - - testname = 'basic test but with nodata present, and a nodata value in input' - allocate(index1(5), index2(5), data(5), data_t(5)) - nodata = -1 - index1 = (/nodata,2,1,2,nodata/) - index2 = (/1,2,3,nodata,nodata/) - fill_val = -1. - data_t = (/fill_val, 22._r8, 13._r8, fill_val, fill_val/) - ierr_t = 0 - call lookup_2d(index1, index2, lookup_table, fill_val, data, ierr, nodata=nodata) - call check_results - deallocate(index1, index2, data, data_t) - - testname = 'valid_entries' - allocate(index1(5), index2(5), data(5), data_t(5)) - index1 = (/1,1,2,2,1/) - index2 = (/1,2,1,2,3/) - valid_entries(1,:) = (/.false.,.false.,.true./) - valid_entries(2,:) = (/.true. ,.true. ,.true./) - fill_val = -1. - data_t = (/fill_val, fill_val, 21._r8, 22._r8, 13._r8/) - ierr_t = 1 - call lookup_2d(index1, index2, lookup_table, fill_val, data, ierr, valid_entries=valid_entries) - call check_results - - testname = 'valid_entries, invalid_okay' - ! Note: this test reuses some setup from the previous test - ierr_t = 0 - call lookup_2d(index1, index2, lookup_table, fill_val, data, ierr, & - valid_entries=valid_entries, invalid_okay=.true.) - call check_results - deallocate(index1, index2, data, data_t) - - - testname = 'valid_entries, together with index out of range' - ! in addition to checking both valid_entries and index out of range, this also - ! makes sure that we get the appropriate ierr value when we have both errors - ! (because we encounter the valid_entries error first) - allocate(index1(5), index2(5), data(5), data_t(5)) - index1 = (/1,1,3,2,2/) - index2 = (/1,2,1,1,0/) - valid_entries(1,:) = (/.false.,.false.,.true./) - valid_entries(2,:) = (/.true. ,.true. ,.true./) - fill_val = -1. - data_t = (/fill_val, fill_val, fill_val, 21._r8, fill_val/) - ierr_t = 1 - call lookup_2d(index1, index2, lookup_table, fill_val, data, ierr, valid_entries=valid_entries) - call check_results - deallocate(index1, index2, data, data_t) - - - deallocate(lookup_table, valid_entries) - - contains - subroutine check_results - call test_is(data, data_t, modname//' -- '//subname//' -- '//trim(testname)//' -- data') - call test_is(ierr, ierr_t, modname//' -- '//subname//' -- '//trim(testname)//' -- ierr') - end subroutine check_results - - end subroutine test_lookup_2d -!------------------------------------------------------------------------------ - -!------------------------------------------------------------------------------ - subroutine test_lookup_2d_netcdf - - use mkncdio - - implicit none - - character(len=128) :: testname - character(len=64) :: tablename - character(len=4) :: dimname1, dimname2 - logical :: invalid_lookup - integer :: n_extra_dims - integer , allocatable :: index1(:), index2(:) - real(r8), allocatable :: data(:), data_t(:) - real(r8) :: fill_val - integer :: nodata - integer :: ierr, ierr_t - type(dim_slice_type), allocatable :: extra_dims(:) - - integer :: ncid - character(len=*), parameter :: filename = 'unit_testers/inputs/test_lookup_2d_netcdf.nc' - - ! flags to enable tests that we don't usually want to run, because they result in - ! an abort, but we may occasionally want to run to make sure this error-handling is - ! working properly - logical, parameter :: test_abort1 = .false. - logical, parameter :: test_abort2 = .false. - logical, parameter :: test_abort3 = .false. - - character(len=*), parameter :: subname = 'test_lookup_2d_netcdf' - - ! Open netcdf file that will be used for most tests: - ! Note that this file was created such that lookup4d(i,j,k,l) = 1000*i+100*j+10*k+l, - ! and similarly for the other variables - ! Also, lookup2d(1,2) is missing (i.e., equal to the _FillVal) - call check_ret(nf_open(filename, 0, ncid), subname) - - testname = '2-d lookup table with _FillValue resulting in valid_entries false somewhere' - allocate(index1(5), index2(5), data(5), data_t(5)) - tablename = 'lookup2d' - invalid_lookup = .true. - dimname1 = 'dim1' - dimname2 = 'dim2' - n_extra_dims = 0 - index1 = (/1,2,1,2,2/) - index2 = (/1,2,2,1,3/) - fill_val = -1. - ! Note that the third value is fill_val because lookup2d(1,2) is missing (i.e., - ! equal to the _FillVal in the netcdf file) - data_t = (/11._r8, 22._r8, fill_val, 21._r8, 23._r8/) - ierr_t = 1 - call lookup_2d_netcdf(ncid, tablename, invalid_lookup, dimname1, dimname2, & - n_extra_dims, index1, index2, fill_val, data, ierr) - call check_results - - testname = '2-d lookup table with _FillValue resulting in valid_entries false somewhere, invalid_okay' - ! Note: this test reuses some setup from the previous test - ierr_t = 0 - call lookup_2d_netcdf(ncid, tablename, invalid_lookup, dimname1, dimname2, & - n_extra_dims, index1, index2, fill_val, data, ierr, invalid_okay=.true.) - call check_results - deallocate(index1, index2, data, data_t) - - testname = '3-d lookup table with no _FillValue; nodata in index arrays' - allocate(index1(5), index2(5), data(5), data_t(5)) - tablename = 'lookup3d' - invalid_lookup = .false. - dimname1 = 'dim1' - dimname2 = 'dim2' - n_extra_dims = 1 - allocate(extra_dims(n_extra_dims)) - extra_dims(1) = dim_slice_type('dim3', 2) - nodata = -999 - index1 = (/nodata,2,1,2,2/) - index2 = (/1,2,2,1,nodata/) - fill_val = -1. - data_t = (/fill_val, 222._r8, 122._r8, 212._r8, fill_val/) - ierr_t = 0 - call lookup_2d_netcdf(ncid, tablename, invalid_lookup, dimname1, dimname2, & - n_extra_dims, index1, index2, fill_val, data, ierr, extra_dims=extra_dims, & - nodata=nodata) - call check_results - deallocate(index1, index2, data, data_t, extra_dims) - - testname = '4-d lookup table' - allocate(index1(5), index2(5), data(5), data_t(5)) - tablename = 'lookup4d' - invalid_lookup = .true. - dimname1 = 'dim1' - dimname2 = 'dim2' - n_extra_dims = 2 - allocate(extra_dims(n_extra_dims)) - extra_dims(1) = dim_slice_type('dim3', 4) - extra_dims(2) = dim_slice_type('dim4', 5) - index1 = (/1,2,1,2,2/) - index2 = (/1,2,2,1,3/) - fill_val = -1. - data_t = (/1145., 2245., 1245., 2145., 2345./) - ierr_t = 0 - call lookup_2d_netcdf(ncid, tablename, invalid_lookup, dimname1, dimname2, & - n_extra_dims, index1, index2, fill_val, data, ierr, extra_dims=extra_dims) - call check_results - deallocate(index1, index2, data, data_t, extra_dims) - - ! The following tests should result in the code aborting with an error message. - ! - ! We don't usually want to run these tests, because they result in the code - ! aborting, but we may want to run them occasionally to make sure this - ! error-handling is working correctly. - - if (test_abort1) then - testname = '2-d lookup table with incorrect dimname for dimension 2' - allocate(index1(5), index2(5), data(5), data_t(5)) - tablename = 'lookup2d' - invalid_lookup = .true. - dimname1 = 'dim1' - dimname2 = 'bad2' ! this differs from the value in the file - n_extra_dims = 0 - index1 = (/1,2,1,2,2/) - index2 = (/1,2,2,1,3/) - fill_val = -1. - ! Note that the third value is fill_val because lookup2d(1,2) is missing (i.e., - ! equal to the _FillVal in the netcdf file) - data_t = (/11._r8, 22._r8, fill_val, 21._r8, 23._r8/) - ierr_t = 1 - call lookup_2d_netcdf(ncid, tablename, invalid_lookup, dimname1, dimname2, & - n_extra_dims, index1, index2, fill_val, data, ierr) - deallocate(index1, index2, data, data_t) - end if - - if (test_abort2) then - testname = '3-d lookup table with incorrect dimname for dimension 3' - allocate(index1(5), index2(5), data(5), data_t(5)) - tablename = 'lookup3d' - invalid_lookup = .false. - dimname1 = 'dim1' - dimname2 = 'dim2' - n_extra_dims = 1 - allocate(extra_dims(n_extra_dims)) - extra_dims(1) = dim_slice_type('bad3', 2) ! this name differs from the value in the file - nodata = -999 - index1 = (/nodata,2,1,2,2/) - index2 = (/1,2,2,1,nodata/) - fill_val = -1. - data_t = (/fill_val, 222._r8, 122._r8, 212._r8, fill_val/) - ierr_t = 0 - call lookup_2d_netcdf(ncid, tablename, invalid_lookup, dimname1, dimname2, & - n_extra_dims, index1, index2, fill_val, data, ierr, extra_dims=extra_dims, & - nodata=nodata) - deallocate(index1, index2, data, data_t, extra_dims) - end if - - if (test_abort3) then - testname = '3-d lookup table, trying to access too large index for dimension 3' - allocate(index1(5), index2(5), data(5), data_t(5)) - tablename = 'lookup3d' - invalid_lookup = .false. - dimname1 = 'dim1' - dimname2 = 'dim2' - n_extra_dims = 1 - allocate(extra_dims(n_extra_dims)) - extra_dims(1) = dim_slice_type('dim3', 5) ! this index is out of bounds - nodata = -999 - index1 = (/nodata,2,1,2,2/) - index2 = (/1,2,2,1,nodata/) - fill_val = -1. - data_t = (/fill_val, 222._r8, 122._r8, 212._r8, fill_val/) - ierr_t = 0 - call lookup_2d_netcdf(ncid, tablename, invalid_lookup, dimname1, dimname2, & - n_extra_dims, index1, index2, fill_val, data, ierr, extra_dims=extra_dims, & - nodata=nodata) - deallocate(index1, index2, data, data_t, extra_dims) - end if - - call check_ret(nf_close(ncid), subname) - - contains - subroutine check_results - call test_is(data, data_t, modname//' -- '//subname//' -- '//trim(testname)//' -- data') - call test_is(ierr, ierr_t, modname//' -- '//subname//' -- '//trim(testname)//' -- ierr') - end subroutine check_results - - end subroutine test_lookup_2d_netcdf -!------------------------------------------------------------------------------ - -!------------------------------------------------------------------------------ - subroutine test_which_max - - implicit none - - real(r8), dimension(:), allocatable :: arr - - character(len=128) :: testname - - real(r8) :: maxval, maxval_t - integer :: maxindex, maxindex_t - - character(len=*), parameter :: subname = 'test_which_max' - - - testname = 'length-1 array' - allocate(arr(1)) - arr = (/3.0/) - maxval_t = 3.0 - maxindex_t = 1 - call which_max(arr, maxval, maxindex) - call check_results - deallocate(arr) - - testname = 'max @ 1' - allocate(arr(5)) - arr = (/5.0, 2.0, 3.0, 2.5, 1.5/) - maxval_t = 5.0 - maxindex_t = 1 - call which_max(arr, maxval, maxindex) - call check_results - deallocate(arr) - - testname = 'max in middle' - allocate(arr(5)) - arr = (/1.0, 2.0, 3.0, 2.5, 1.5/) - maxval_t = 3.0 - maxindex_t = 3 - call which_max(arr, maxval, maxindex) - call check_results - deallocate(arr) - - testname = 'max at end' - allocate(arr(5)) - arr = (/1.0, 2.0, 3.0, 2.5, 8.0/) - maxval_t = 8.0 - maxindex_t = 5 - call which_max(arr, maxval, maxindex) - call check_results - deallocate(arr) - - testname = 'multiple tied max values' - allocate(arr(5)) - arr = (/1.0, 3.0, 3.0, 2.5, 1.5/) - maxval_t = 3.0 - maxindex_t = 2 - call which_max(arr, maxval, maxindex) - call check_results - deallocate(arr) - - testname = 'max in middle, with lbound present' - allocate(arr(3:7)) - arr = (/1.0, 3.0, 10.0, 2.5, 8.0/) - maxval_t = 10.0 - maxindex_t = 5 - call which_max(arr, maxval, maxindex, lbound=3) - call check_results - deallocate(arr) - - contains - subroutine check_results - call test_is(maxval, maxval_t, modname//' -- '//subname//' -- '//trim(testname)//' -- maxval') - call test_is(maxindex, maxindex_t, modname//' -- '//subname//' -- '//trim(testname)//' -- maxindex') - end subroutine check_results - - end subroutine test_which_max -!------------------------------------------------------------------------------ - -end module test_mkindexmapMod - diff --git a/tools/mksurfdata_map/unit_testers/test_mkncdio.F90 b/tools/mksurfdata_map/unit_testers/test_mkncdio.F90 deleted file mode 100644 index b96dc47071..0000000000 --- a/tools/mksurfdata_map/unit_testers/test_mkncdio.F90 +++ /dev/null @@ -1,82 +0,0 @@ -module test_mkncdio -! Module for testing mkncdio - - use mkncdio - use test_mod - - implicit none - private - - public :: test_get_dim_lengths - public :: test_get_nonexisting_var - - character(len=*), parameter :: modname = 'test_mkncdio' - -contains - -!------------------------------------------------------------------------------ - subroutine test_get_dim_lengths - - implicit none - - character(len=128) :: testname - integer :: ncid - character(len=128) :: varname - integer :: ndims, ndims_t - integer :: dim_lengths(nf_max_var_dims), dim_lengths_t(nf_max_var_dims) - - character(len=*), parameter :: filename = 'unit_testers/inputs/test_lookup_2d_netcdf.nc' - - character(len=*), parameter :: subname = 'test_get_dim_lengths' - - ! Open netcdf file that will be used for most tests - call check_ret(nf_open(filename, 0, ncid), subname) - - testname = '3d variable' - varname = 'lookup3d' - ndims_t = 3 - dim_lengths_t = 0 - dim_lengths_t(1) = 2 - dim_lengths_t(2) = 3 - dim_lengths_t(3) = 4 - call get_dim_lengths(ncid, varname, ndims, dim_lengths) - call check_results - - call check_ret(nf_close(ncid), subname) - - contains - subroutine check_results - call test_is(ndims, ndims_t, modname//' -- '//subname//' -- '//trim(testname)//' -- ndims') - call test_is(dim_lengths(1:ndims), dim_lengths_t(1:ndims_t), & - modname//' -- '//subname//' -- '//trim(testname)//' -- dim_lengths') - end subroutine check_results - - end subroutine test_get_dim_lengths - -!------------------------------------------------------------------------------ - subroutine test_get_nonexisting_var - - implicit none - - character(len=128) :: testname - integer :: ncid - character(len=128) :: varname - integer :: varid - logical :: varexists - - character(len=*), parameter :: filename = 'unit_testers/inputs/test_lookup_2d_netcdf.nc' - - character(len=*), parameter :: subname = 'test_get_nonexiting_var' - - testname = 'check if variables exist' - varname = 'lookup3d' - ! Open netcdf file that will be used for most tests - call check_ret(nf_open(filename, 0, ncid), subname) - call check_ret(nf_inq_varid(ncid, "zztop", varid), subname, varexists=varexists) - call test_is(.not.varexists, modname//' -- '//subname//' -- '//trim(testname)//' -- non existing var') - call check_ret(nf_inq_varid(ncid, varname, varid), subname, varexists=varexists) - call test_is(varexists, modname//' -- '//subname//' -- '//trim(testname)//' -- existing var') - - end subroutine test_get_nonexisting_var - -end module test_mkncdio diff --git a/tools/mksurfdata_map/unit_testers/test_mksurfdata_map.F90 b/tools/mksurfdata_map/unit_testers/test_mksurfdata_map.F90 deleted file mode 100644 index cb5f7f9b72..0000000000 --- a/tools/mksurfdata_map/unit_testers/test_mksurfdata_map.F90 +++ /dev/null @@ -1,52 +0,0 @@ -! Run unit tests for mksurfdata_map -program mksurfdata_map_unit_tester - use test_mkdomainMod - use test_mkutilsMod - use test_mkgridmapMod - use test_mkindexmapMod - use test_mkchecksMod - use test_mkurbanparMod - use test_mkncdio - use test_mkharvest - use test_mod, only : test_init, test_final - - call test_init - - ! Test mkdomainMod - call test_domain_read_dims - - ! Test mkutilsMod - call test_slightly_below - call test_slightly_above - - ! Test mkgridmapMod - call test_gridmap_areaave_no_srcmask - call test_gridmap_areaave_srcmask - call test_gridmap_areastddev - - ! Test mkindexmapMod - call test_get_dominant_indices - call test_lookup_2d - call test_lookup_2d_netcdf - call test_which_max - - ! Test mkchecksMod - call test_min_bad - call test_max_bad - - ! Test mkurbanparMod - call test_normalize_urbn_by_tot - - ! Test mkharvestMod - call test_harvest_init - call test_harvest_init_old - call test_harvest_data_all1D - call test_harvest_data - - ! Test mkncdio - call test_get_dim_lengths - call test_get_nonexisting_var - - call test_final - -end program mksurfdata_map_unit_tester diff --git a/tools/mksurfdata_map/unit_testers/test_mkurbanparMod.F90 b/tools/mksurfdata_map/unit_testers/test_mkurbanparMod.F90 deleted file mode 100644 index 30168eb97c..0000000000 --- a/tools/mksurfdata_map/unit_testers/test_mkurbanparMod.F90 +++ /dev/null @@ -1,75 +0,0 @@ -module test_mkurbanparMod -! Module for testing mkurbanparMod - - use mkurbanparMod - use test_mod - use shr_kind_mod, only : r8 => shr_kind_r8 - - implicit none - private - - public :: test_normalize_urbn_by_tot - - character(len=*), parameter :: modname = 'test_mkurbanparMod' - -contains - -!------------------------------------------------------------------------------ - subroutine test_normalize_urbn_by_tot - - use mkutilsMod, only : normalize_classes_by_gcell - - implicit none - - character(len=128) :: testname - - real(r8), allocatable :: classes_pct_gcell_t(:,:) - real(r8), allocatable :: classes_pct_gcell(:,:) - real(r8), allocatable :: classes_pct_tot(:,:) - real(r8), allocatable :: sums(:) - - integer :: n,nmax,nclass,totsize - - real(r8), parameter :: eps = 1.e-13_r8 - - character(len=*), parameter :: subname = 'test_normalize_urbn_by_tot' - - - ! This test does a basic check of both normalize_urbn_by_tot and - ! normalize_classes_by_gcell, by ensuring that when the two are called in - ! succession, the result is the same as the initial values - ! (Note that it doesn't directly check the intermediate values -- i.e. the output - ! produced by normalize_urbn_by_tot) - testname = 'normalize_urbn_by_tot then normalize_classes_by_gcell' - nmax = 7 - nclass = 3 - totsize = nmax*nclass - allocate(classes_pct_gcell_t(nmax,nclass), & - classes_pct_gcell (nmax,nclass), & - classes_pct_tot (nmax,nclass), & - sums (nmax)) - - ! The following values are designed to test a number of things, including summing - ! to 100, summing to 0, some values 0 for a given n, and no values being 0 for a - ! given n - classes_pct_gcell_t(:,1) = (/ 0., 5., 0., 0., 10., 0., 10./) - classes_pct_gcell_t(:,2) = (/ 0., 0., 0., 100., 30., 15., 50./) - classes_pct_gcell_t(:,3) = (/100., 30., 0., 0., 20., 0., 40./) - - do n = 1, nmax - sums(n) = sum(classes_pct_gcell_t(n,:)) - end do - - call normalize_urbn_by_tot(classes_pct_gcell_t, sums, classes_pct_tot) - call normalize_classes_by_gcell(classes_pct_tot, sums, classes_pct_gcell) - call test_close(reshape(classes_pct_gcell, (/totsize/)), & - reshape(classes_pct_gcell_t, (/totsize/)), & - eps, modname//' -- '//subname//' -- '//trim(testname), rel_diff=.true.) - - deallocate(classes_pct_gcell_t, classes_pct_gcell, classes_pct_tot, sums) - - - end subroutine test_normalize_urbn_by_tot -!------------------------------------------------------------------------------ - -end module test_mkurbanparMod diff --git a/tools/mksurfdata_map/unit_testers/test_mkutilsMod.F90 b/tools/mksurfdata_map/unit_testers/test_mkutilsMod.F90 deleted file mode 100644 index 53b5b1b8c3..0000000000 --- a/tools/mksurfdata_map/unit_testers/test_mkutilsMod.F90 +++ /dev/null @@ -1,112 +0,0 @@ -module test_mkutilsMod -! Module for testing mkutilsMod - - use mkutilsMod - use test_mod - use shr_kind_mod, only : r8 => shr_kind_r8 - - implicit none - private - - public :: test_slightly_below - public :: test_slightly_above - - character(len=*), parameter :: modname = 'test_mkutilsMod' - -contains - -!------------------------------------------------------------------------------ - subroutine test_slightly_below - - implicit none - - character(len=128) :: testname - - logical :: retval - real(r8) :: a - real(r8) :: b - - character(len=*), parameter :: subname = 'test_slightly_below' - - testname='basic-true' - b = 3.0 - a = 3.0 - b*epsilon(b) - retval = slightly_below(a,b) - call test_is((retval .eqv. .true.), modname//' -- '//subname//' -- '//trim(testname)) - - testname='far below' - b = 3.0 - a = 2.0 - retval = slightly_below(a,b) - call test_is((retval .eqv. .false.), modname//' -- '//subname//' -- '//trim(testname)) - - testname='equal' - b = 3.0 - a = 3.0 - retval = slightly_below(a,b) - call test_is((retval .eqv. .false.), modname//' -- '//subname//' -- '//trim(testname)) - - testname='above' - b = 3.0 - a = 3.0 + epsilon(b) - retval = slightly_below(a,b) - call test_is((retval .eqv. .false.), modname//' -- '//subname//' -- '//trim(testname)) - - testname='change epsilon to allow far below' - b = 3.0 - a = 2.0 - retval = slightly_below(a,b,eps=0.75_r8) - call test_is((retval .eqv. .true.), modname//' -- '//subname//' -- '//trim(testname)) - - end subroutine test_slightly_below -!------------------------------------------------------------------------------ - -!------------------------------------------------------------------------------ - subroutine test_slightly_above - - implicit none - - character(len=128) :: testname - - logical :: retval - real(r8) :: a - real(r8) :: b - - character(len=*), parameter :: subname = 'test_slightly_above' - - testname='basic-true' - b = 3.0 - a = 3.0 + b*epsilon(b) - retval = slightly_above(a,b) - call test_is((retval .eqv. .true.), modname//' -- '//subname//' -- '//trim(testname)) - - testname='far above' - b = 3.0 - a = 4.0 - retval = slightly_above(a,b) - call test_is((retval .eqv. .false.), modname//' -- '//subname//' -- '//trim(testname)) - - testname='equal' - b = 3.0 - a = 3.0 - retval = slightly_above(a,b) - call test_is((retval .eqv. .false.), modname//' -- '//subname//' -- '//trim(testname)) - - testname='below' - b = 3.0 - a = 3.0 - epsilon(b) - retval = slightly_above(a,b) - call test_is((retval .eqv. .false.), modname//' -- '//subname//' -- '//trim(testname)) - - testname='change epsilon to allow far above' - b = 3.0 - a = 4.0 - retval = slightly_above(a,b,eps=0.75_r8) - call test_is((retval .eqv. .true.), modname//' -- '//subname//' -- '//trim(testname)) - - end subroutine test_slightly_above -!------------------------------------------------------------------------------ - -end module test_mkutilsMod - - diff --git a/tools/mksurfdata_map/unit_testers/test_mod.F90 b/tools/mksurfdata_map/unit_testers/test_mod.F90 deleted file mode 100644 index 967eee1c89..0000000000 --- a/tools/mksurfdata_map/unit_testers/test_mod.F90 +++ /dev/null @@ -1,339 +0,0 @@ -module test_mod - -use shr_kind_mod, only : SHR_KIND_R8 -use shr_sys_mod, only : shr_sys_abort - -implicit none - -public test_init -public test_is -public test_close -public test_final - -integer, save :: ntests = 0 -integer, save :: npass = 0 -integer, save :: num_expected = 0 -logical, save :: num_expected_given = .false. -character(*), parameter :: formatTest = '(A4, " ", i5.5, " - ", A)' -character(*), parameter :: formatArrayMatch = & - '(" (all ", i5, " values match)")' -character(*), parameter :: formatArray2DMatch = & - '(" (all ", i5, "x", i5, " values match)")' -character(*), parameter :: formatArrayMisMatch = & - '(" (only ", i5, " values of ", i5, " values match)")' -character(*), parameter :: formatArray2DMisMatch = & - '(" (only ", i5, " values of ", i5, "x", i5, " values match)")' -character(*), parameter :: formatRArrayClose = & - '(" (all ", i5, " values are within", 1pe9.1e2, " )")' -character(*), parameter :: formatRArrayNotClose = & - '(" (only ", i5, " values of ", i5, " values are within", 1pe9.1e2, " max diff= ", 1pe9.1e2, ")")' -character(*), parameter :: formatRClose = & - '(" ( value within", 1pe9.1e2, " )")' -character(*), parameter :: formatRNotClose = & - '(" ( value within", 1pe9.1e2, " diff= ", 1pe9.1e2, ")")' - -interface test_is - module procedure test_is_logical - module procedure test_is_logical1D - module procedure test_is_string - module procedure test_is_integer - module procedure test_is_integer1D - module procedure test_is_real1D - module procedure test_is_real2D - module procedure test_is_realScalar -end interface test_is - -interface test_close - module procedure test_close_real1D - module procedure test_close_realScalar -end interface test_close - -private test_is_logical -private test_is_string -private test_is_integer -private test_is_integer1D -private test_is_real1D -private test_is_realScalar -private test_close_real1D - -contains - - -subroutine test_init( num_expected_tests ) - integer, intent(IN), optional :: num_expected_tests - - if ( present(num_expected_tests) ) then - num_expected = num_expected_tests - num_expected_given = .true. - write(*,formatTest) "1...", num_expected, "expected tests" - write(*,*) - end if - -end subroutine test_init - -subroutine test_is_logical( pass, description ) - - implicit none - - logical, intent(IN) :: pass ! If matches or not - character(*), intent(IN) :: description ! description of test - - character(4) :: status - - ntests = ntests + 1 - if ( pass )then - npass = npass + 1 - status = "PASS" - else - status = "FAIL" - end if - write(*,formatTest) status, ntests, trim(description) - -end subroutine test_is_logical - -subroutine test_is_logical1D( value, expected, description ) - - implicit none - - logical, intent(IN) :: value(:) ! test value - logical, intent(IN) :: expected(:) ! expected value - character(*), intent(IN) :: description ! description of test - - logical :: pass - integer :: nsize, nmatch - character(256) :: descrip - - nsize = size(value) - if ( all(value .eqv. expected) )then - pass = .true. - write(descrip,formatArrayMatch) nsize - else - nmatch = count(value .eqv. expected) - write(descrip,formatArrayMisMatch) nmatch, nsize - pass = .false. - end if - call test_is_logical( pass, trim(description)//trim(descrip) ) - -end subroutine test_is_logical1D - - -subroutine test_is_string( value, expected, description ) - - implicit none - - character(len=*), intent(IN) :: value - character(len=*), intent(IN) :: expected - character(len=*), intent(IN) :: description ! description of test - - - logical :: pass ! If matches or not - - character(4) :: status - - if ( trim(value) == trim(expected) )then - pass = .true. - else - pass = .false. - end if - ntests = ntests + 1 - if ( pass )then - npass = npass + 1 - status = "PASS" - else - status = "FAIL" - end if - write(*,formatTest) status, ntests, trim(description) - -end subroutine test_is_string - -subroutine test_is_integer( value, expected, description ) - integer, intent(IN) :: value ! test value - integer, intent(IN) :: expected ! expected value - character(*), intent(IN) :: description ! description of test - - logical :: pass - - if ( value == expected )then - pass = .true. - else - pass = .false. - end if - call test_is_logical( pass, description ) - -end subroutine test_is_integer - -subroutine test_is_integer1D( value, expected, description ) - integer, intent(IN) :: value(:) ! test value - integer, intent(IN) :: expected(:) ! expected value - character(*), intent(IN) :: description ! description of test - - logical :: pass - integer :: nsize, nmatch - character(256) :: descrip - - nsize = size(value) - if ( all(value == expected) )then - pass = .true. - write(descrip,formatArrayMatch) nsize - else - nmatch = count(value == expected) - write(descrip,formatArrayMisMatch) nmatch, nsize - pass = .false. - end if - call test_is_logical( pass, trim(description)//trim(descrip) ) - -end subroutine test_is_integer1D - -subroutine test_is_real1D( value, expected, description ) - real(SHR_KIND_R8), intent(IN) :: value(:) ! test value - real(SHR_KIND_R8), intent(IN) :: expected(:) ! expected value - character(*), intent(IN) :: description ! description of test - - logical :: pass - integer :: nsize, nmatch - character(256) :: descrip - - nsize = size(value) - if ( all(value == expected) )then - pass = .true. - write(descrip,formatArrayMatch) nsize - else - nmatch = count(value == expected) - write(descrip,formatArrayMisMatch) nmatch, nsize - pass = .false. - end if - call test_is_logical( pass, trim(description)//trim(descrip) ) - -end subroutine test_is_real1D - -subroutine test_is_real2D( value, expected, description ) - real(SHR_KIND_R8), intent(IN) :: value(:,:) ! test value - real(SHR_KIND_R8), intent(IN) :: expected(:,:) ! expected value - character(*), intent(IN) :: description ! description of test - - logical :: pass - integer :: nsize1, nsize2, nmatch - character(256) :: descrip - - nsize1 = size(value,1) - nsize2 = size(value,2) - if ( all(value == expected) )then - pass = .true. - write(descrip,formatArray2DMatch) nsize1, nsize2 - else - nmatch = count(value == expected) - write(descrip,formatArray2DMisMatch) nmatch, nsize1, nsize2 - pass = .false. - end if - call test_is_logical( pass, trim(description)//trim(descrip) ) - -end subroutine test_is_real2D - -subroutine test_is_realScalar( value, expected, description ) - real(SHR_KIND_R8), intent(IN) :: value ! test value - real(SHR_KIND_R8), intent(IN) :: expected ! expected value - character(*), intent(IN) :: description ! description of test - - logical :: pass - - if ( value == expected )then - pass = .true. - else - pass = .false. - end if - call test_is_logical( pass, description ) - -end subroutine test_is_realScalar - -subroutine test_close_real1D( value, expected, eps, description, rel_diff ) - real(SHR_KIND_R8), intent(IN) :: value(:) ! test value - real(SHR_KIND_R8), intent(IN) :: expected(:) ! expected value - real(SHR_KIND_R8), intent(IN) :: eps ! epsilon -- how close to be within - character(*), intent(IN) :: description ! description of test - logical, optional, intent(IN) :: rel_diff ! if should do relative difference or not - - logical :: pass, lreldiff - integer :: nsize, nmatch, i, n0(1), nf(1) - real(SHR_KIND_R8) :: within, diff - character(256) :: descrip - - lreldiff = .false. - if ( present(rel_diff) ) lreldiff = rel_diff - nsize = size(value) - if ( nsize /= size(expected) )then - call shr_sys_abort( "size of value and expected array is different" ) - end if - if ( any(lbound(value) /= lbound(expected)) )then - call shr_sys_abort( "lower bound of value and expected array is different" ) - end if - nmatch = 0 - n0 = lbound(value) - nf = ubound(value) - within = abs(value(n0(1)) - expected(n0(1))) - if ( lreldiff .and. within > 0.0_SHR_KIND_R8 ) within = within / max( abs(value(n0(1))), abs(expected(n0(1))) ) - do i = n0(1), nf(1) - diff = abs(value(i) - expected(i)) - if ( lreldiff .and. diff > 0.0_SHR_KIND_R8 ) diff = diff / max(abs(value(i)),abs(expected(i)) ) - within = max( within, diff ) - if ( diff <= eps ) nmatch = nmatch + 1 - end do - if( nmatch == nsize )then - write(descrip,formatRArrayClose) nsize, eps - pass = .true. - else - write(descrip,formatRArrayNotClose) nmatch, nsize, eps, within - pass = .false. - end if - call test_is_logical( pass, trim(description)//trim(descrip) ) - -end subroutine test_close_real1D - -subroutine test_close_realScalar( value, expected, eps, description ) - real(SHR_KIND_R8), intent(IN) :: value ! test value - real(SHR_KIND_R8), intent(IN) :: expected ! expected value - real(SHR_KIND_R8), intent(IN) :: eps ! epsilon -- how close to be within - character(*), intent(IN) :: description ! description of test - - logical :: pass - real(SHR_KIND_R8) :: diff - character(256) :: descrip - - diff = abs(value - expected) - if ( diff <= eps ) then - write(descrip,formatRClose) eps - pass = .true. - else - write(descrip,formatRNotClose) eps, diff - pass = .false. - end if - call test_is_logical( pass, trim(description)//trim(descrip) ) - -end subroutine test_close_realScalar - -subroutine test_final( PassStatus ) - - logical, intent(OUT), optional :: PassStatus - - character(4) :: status - character(50) :: desc - - write(*,*) - status = "PASS" - if ( present(PassStatus) ) PassStatus = .true. - desc = "All expected tests ran successfully" - if ( num_expected_given .and. ntests /= num_expected )then - status = "FAIL" - desc = "Different number of tests than expected" - if ( present(PassStatus) ) PassStatus = .false. - end if - if ( npass /= ntests )then - status = "FAIL" - if ( present(PassStatus) ) PassStatus = .false. - write(desc,'(A,i3,A)') "Not all tests passed (", & - ntests-npass, " tests failed)" - end if - write(*,formatTest) status, ntests, "tests run -- "//desc - -end subroutine test_final - -end module test_mod diff --git a/tools/modify_input_files/README.mesh_mask_modifier b/tools/modify_input_files/README.mesh_mask_modifier index 4e25e73826..b667ebf22f 100644 --- a/tools/modify_input_files/README.mesh_mask_modifier +++ b/tools/modify_input_files/README.mesh_mask_modifier @@ -36,12 +36,8 @@ F-Case, modifying the continental geometry User wants to make the Indian Ocean into grassland. They specify their own land fraction mask on the CESM 1-degree grid, as well as the area to be specified as grassland in a netcdf file. This has been obtained by -modifying the default land fraction of CESM. An example netcdf file -containing the masks for such a case is on cheyenne: +modifying the default land fraction of CESM. The file contains two arrays: -/glade/work/slevis/git/mksurfdata_toolchain/tools/modify_input_files/islas_examples/modify_mesh_mask/fill_indian_ocean/fill_indianocean_slevis.nc - -This contains two arrays: - landmask = the new landmask - mod_lnd_props = set to 1 where the new land surface has been specified (i.e., where grassland needs to be specified) and zero elsewhere diff --git a/tools/modify_input_files/modify_fsurdat_template.cfg b/tools/modify_input_files/modify_fsurdat_template.cfg index 1dfb33ce53..3d18189d51 100644 --- a/tools/modify_input_files/modify_fsurdat_template.cfg +++ b/tools/modify_input_files/modify_fsurdat_template.cfg @@ -29,8 +29,8 @@ fsurdat_out = FILL_THIS_IN # defaults, then set this to True. Hardwired values are as follows: # zbedrock = 10 # SLOPE = 0 -# PFTDATA_MASK = 1 # LANDFRAC_PFT = 1 +# LANDFRAC_MKSURFDATA = 1 # PCT_NATVEG = 100 other landunits 0 # PCT_SAND = 43 corresponds to loam # PCT_CLAY = 18 corresponds to loam diff --git a/tools/modify_input_files/modify_smallville.sh b/tools/modify_input_files/modify_smallville.sh new file mode 100755 index 0000000000..4dc7c58e9b --- /dev/null +++ b/tools/modify_input_files/modify_smallville.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +# Script that prepares landuse files for smallvilleIA. +# Load the nco module and run the script in the ctsm_pylib environment: +module load nco + +# This script runs from the mksurfdata_esmf/Makefile. +# When running standalone, it may need "subset_data_single_point/" in front +# of each landuse.timeseries file name. + file_to_2100="landuse.timeseries_1x1_smallvilleIA_SSP2-4.5_1850-2100_78pfts_c$(date +%y%m%d).nc" + file_to_1855="landuse.timeseries_1x1_smallvilleIA_SSP2-4.5_1850-1855_78pfts_c$(date +%y%m%d).nc" + file_lake="landuse.timeseries_1x1_smallvilleIA_SSP2-4.5_1850-1855_78pfts_dynLakes_c$(date +%y%m%d).nc" + file_urban="landuse.timeseries_1x1_smallvilleIA_SSP2-4.5_1850-1855_78pfts_dynUrban_c$(date +%y%m%d).nc" + file_pft="landuse.timeseries_1x1_smallvilleIA_SSP2-4.5_1850-1855_78pfts_dynPft_c$(date +%y%m%d).nc" + +# Trim the file to just the years 1850-1855 +ncks -d time,0,5 $file_to_2100 $file_to_1855 + +# Replace all values in the LAKE and CROP variables +ncap2 -s "PCT_LAKE=array(0.,0.,PCT_CROP); PCT_LAKE={0.,50.,25.,25.,25.,25.} ; PCT_LAKE_MAX=array(50.,50.,PCT_CROP_MAX); PCT_CROP=array(0.,0.,PCT_LAKE); PCT_CROP={0.,25.,12.,12.,12.,12.}; PCT_CROP_MAX=array(25.,25.,PCT_LAKE_MAX)" $file_to_1855 $file_lake + +# Replace all values in the URBAN and CROP variables +ncap2 -s "PCT_URBAN=array(0.,0.,PCT_URBAN); PCT_URBAN={0.,0.,0.,20.,15.,0.,10.,8.,0.,10.,8.,0.,10.,8.,0.,10.,8.,0.} ; PCT_URBAN_MAX=array(0.,0.,PCT_URBAN_MAX); PCT_URBAN_MAX={20.,15.,0.}; PCT_CROP=array(0.,0.,PCT_LAKE); PCT_CROP={0.,25.,12.,12.,12.,12.}; PCT_CROP_MAX=array(25.,25.,PCT_LAKE_MAX)" $file_to_1855 $file_urban + +# Update values in the pft, cft, harvest, and grazing variables as posted here: +# https://github.com/ESCOMP/CTSM/issues/1673#issuecomment-1879156989 +ncap2 -s "PCT_NAT_PFT=array(0.,0.,PCT_NAT_PFT); PCT_NAT_PFT={0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,100.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,100.,0.,100.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,100.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,50.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,50.,0.,25.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,75.,0.} ; PCT_NAT_PFT_MAX=array(0.,0.,PCT_NAT_PFT_MAX); PCT_NAT_PFT_MAX={100.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,100.,0.}; PCT_CFT=array(0.,0.,PCT_CFT); PCT_CFT={100.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,100.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,1.,1.,1.,1.,1.,1.,1.,1.,1.,91.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,91.,1.,1.,1.,1.,1.,1.,1.,1.,1.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,2.,4.,4.,6.,6.,8.,8.,10.,10.,42.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,4.,4.,4.,4.,4.,4.,4.,4.,4.,64.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.}; PCT_CFT_MAX=array(0.,0.,PCT_CFT_MAX); PCT_CFT_MAX={100.,2.,2.,3.,3.,4.,4.,5.,5.,91.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.}; PCT_CROP=array(0.,0.,PCT_CROP); PCT_CROP={0.,0.,100.,100.,50.,25.}; PCT_CROP_MAX=array(100.,100.,PCT_CROP_MAX); HARVEST_SH1=array(0.,0.,HARVEST_SH1); HARVEST_SH1={0.,0.,0.,0.,0.,0.}; HARVEST_SH2=array(0.,0.,HARVEST_SH2); HARVEST_SH2={0.,0.,0.,0.,0.,0.}; HARVEST_SH3=array(0.,0.,HARVEST_SH3); HARVEST_SH3={0.,0.,0.,0.,0.,0.}; HARVEST_VH1=array(0.,0.,HARVEST_VH1); HARVEST_VH1={0.,0.,0.,0.,0.,0.}; HARVEST_VH2=array(0.,0.,HARVEST_VH2); HARVEST_VH2={0.,0.,0.,0.,0.,0.}; GRAZING=array(0.,0.,GRAZING); GRAZING={0.,0.,0.,0.,0.,0.}" $file_to_1855 $file_pft + +exit diff --git a/tools/ncl_scripts/README b/tools/ncl_scripts/README deleted file mode 100644 index 72073f5035..0000000000 --- a/tools/ncl_scripts/README +++ /dev/null @@ -1,15 +0,0 @@ -$CTSMROOT/tools/ncl_scripts Jun/08/2018 - -CLM NCL script tools for analysis of CLM history files -- or for creation or -modification of CLM input files. - -In order to make these scripts work in the testing framework the following must -be done. - -1.) Respond to CSMDATA and CLM_ROOT as needed. -2.) Print a line with "success" after the work is completed. - -NCL Scripts available: - -getco2_historical.ncl ------- Get historical CO2 to use for input in datm8 streams - diff --git a/tools/ncl_scripts/getco2_historical.ncl b/tools/ncl_scripts/getco2_historical.ncl deleted file mode 100644 index c071fa42d6..0000000000 --- a/tools/ncl_scripts/getco2_historical.ncl +++ /dev/null @@ -1,196 +0,0 @@ -; -; Take the greenhouse gas file used by CAM for historical (and future) representations of -; greenhouse gases, and convert it to a format that can be used by streams. -; So include domain data for a single point (or latitude bands) that covers the globe, as well -; as CO2 data over those latitude bands. In the process we also discard the other -; greenhouse gases, as the datm can only pass CO2. -; -; Erik Kluzek -; Mar/03/2010 -; -begin - ; =========================================================================================================== - - - ; =========================================================================================================== - ; - ; Setup the namelist query script - ; - csmdata = getenv("CSMDATA"); - clmroot = getenv("CLM_ROOT"); - hgrid = getenv("HGRID"); ; Get horizontal grid to use from env variable - querynml = "bld/queryDefaultNamelist.pl -silent -justvalue "; - if ( .not. ismissing(csmdata) )then - querynml = querynml+" -csmdata "+csmdata; - end if - if ( ismissing(clmroot) )then - querynml = "../../"+querynml; - else - querynml = clmroot+"/"+querynml; - end if - if ( ismissing(hgrid) )then - hgrid = "lat-bands" - end if - ; - ; Get input Greenhouse gas file and open it - ; - filetype = "mkghg_bndtvghg"; - print( querynml+" -namelist clmexp -var "+filetype+" -options hgrid="+hgrid ); - ghgfile = systemfunc( querynml+" -namelist clmexp -var "+filetype+" -options hgrid="+hgrid ); - print( "Use "+filetype+" file: "+ghgfile ); - if ( systemfunc("test -f "+ghgfile+"; echo $?" ) .ne. 0 )then - print( "Input "+filetype+" file does not exist or not found: "+ghgfile ); - exit - end if - ncg = addfile( ghgfile, "r" ); - - ; - ; Get date time-stamp to put on output CO2 file - ; - sdate = systemfunc( "date +%y%m%d" ); - ldate = systemfunc( "date" ); - - sim_yr0 = ncg->date(0) / 10000; - ntime = dimsizes( ncg->date ); - sim_yr2 = ncg->date(ntime-1) / 10000; - - sim_yr_rng = "simyr_"+sim_yr0 + "-" + sim_yr2; - - cmip_vers = "_CMIP6_"; - outco2filename = "fco2_datm_"+hgrid+sim_yr_rng+cmip_vers+"c"+sdate+".nc"; - system( "/bin/rm -f "+outco2filename ); - print( "output file: "+outco2filename ); - nco = addfile( outco2filename, "c" ); - ; - ; Define dimensions - ; - if ( hgrid .eq. "lat-bands" )then - nlat = dimsizes(ncg->lat); - else - if ( hgrid .eq. "global" )then - nlat = 1 - else - print( "hgrid type can only be global or lat-bands: "+hgrid ) - exit - end if - end if - nlon = 1; - nv = 4; - dimnames = (/ "time", "lat", "lon", "nv", "bounds" /); - dsizes = (/ ntime, nlat, nlon, nv, 2 /); - is_unlim = (/ True, False, False, False, False /); - filedimdef( nco, dimnames, dsizes, is_unlim ); - ; - ; Define variables - ; - vars = (/ "lonc", "latc", "lonv", "latv", "mask", "frac", "area", "CO2" /); - units= (/ "degrees_east", "degrees_north", "degree_east", "degrees_north", "unitless", "unitless", "radians^2", "ppmv" /); - lname= (/ "Longitude of grid cell center", "Latitude of grid cell center", "Longitudes of grid cell vertices", "Latitudes of grid cell vertices", "Mask of active cells: 1=active", "Fraction of grid cell that is active", "Area of grid cell", "CO2 concentration" /); - print( "Define variables: "+vars ); - do i= 0, dimsizes(vars)-1 - if ( vars(i) .eq. "lonv" .or. vars(i) .eq. "latv" )then - filevardef ( nco, vars(i), "double", (/ "lat", "lon", "nv" /) ); - else - if ( vars(i) .eq. "CO2" )then - filevardef ( nco, vars(i), "float", (/ "time", "lat", "lon" /) ); - nco->$vars(i)$@coordinate = "latc lonc time"; - else - filevardef ( nco, vars(i), "double", (/ "lat", "lon" /) ); - end if - end if - nco->$vars(i)$@units = units(i); - nco->$vars(i)$@long_name = lname(i); - end do - filevardef ( nco, "time", "float", (/ "time" /) ); - filevardef ( nco, "time_bnds", "float", (/ "time", "bounds" /) ); - filevardef ( nco, "date", "integer", (/ "time" /) ); - varstatic = (/ "mask", "frac", "area" /); - do i = 0, dimsizes(varstatic)-1 - nco->$varstatic(i)$@coordinate = "latc lonc"; - end do - nco->lonc@bounds = "lonv"; - nco->latc@bounds = "latv"; - ; - ; Add attributes - ; - fileattdef ( nco, ncg ); - nco@history = ldate+": Convert by getco2_historical.ncl"; - nco@source = "Convert from:"+ghgfile; - nco@Version = systemfunc( "git describe" ); - filevarattdef( nco, "time", ncg->time ); - filevarattdef( nco, "date", ncg->date ); - nco->time_bnds@long_name = nco->time@long_name; - nco->time_bnds@units = nco->time@units; - nco->time_bnds@calendar = nco->time@calendar; - ; - ; Set static variables - ; - pi = 3.14159265358979323846d00; - nco->mask = 1; - nco->frac = 1.0; - if ( nlat .gt. 1 )then - nco->latc = (/ ncg->lat/); - else - nco->latc = (/ 0.0d00 /); - end if - nco->latv(nlat-1,0,0) = 90.0d00; - nco->latv(nlat-1,0,3) = 90.0d00; - if ( nlat .gt. 1 )then - nco->latv(0:nlat-2,0,0) = ( (/ ncg->lat(0:nlat-2) /) + (/ncg->lat(1:nlat-1) /) )*0.5d00 - nco->latv(0:nlat-2,0,3) = (/ nco->latv(0:nlat-2,0,0) /); - nco->latv(1:nlat-1,0,1) = (/ nco->latv(0:nlat-2,0,0) /); - nco->latv(1:nlat-1,0,2) = (/ nco->latv(1:nlat-1,0,1) /); - end if - nco->latv(0,0,1) = -90.0d00; - nco->latv(0,0,2) = -90.0d00; - nco->lonv(:,0,0) = 0.0d00; - nco->lonv(:,0,3) = 0.0d00; - nco->lonc = 180.0d00; - nco->lonv(:,0,1) = 360.0d00; - nco->lonv(:,0,2) = 360.0d00; - clkws = gc_clkwise( nco->latv, nco->lonv ); - if ( any(clkws .eq. False) )then - print( "Some varticies are NOT clockwise" ); - exit - end if - ; EBK -- NOTE The NCL function wasn't giving me the correct answer so I used the mathmatical expression - ;nco->area = dble2flt( gc_qarea( nco->latv, nco->lonv ) ); - conv2rad = pi/180.0d00 - nco->area(:,0) = 2.0d00*pi*abs( sin((/nco->latv(:,0,0)/)*conv2rad) - sin((/nco->latv(:,0,1)/)*conv2rad) ); - if ( abs(sum(nco->area) - 4.0d00*pi) .gt. 1.d-14 )then - print( "Area of globe does not sum to 4*pi as expected" ); - exit - end if - ; - ; Time and date - ; - nco->date = (/ ncg->date /); - nco->time = (/ ncg->time /); - nco->time_bnds = (/ ncg->time_bnds /); - nco->date@comment = "This variable is NOT used when read by datm, the time coordinate is used"; - ; - ; CO2 - ; - print( "Copy CO2 for "+ntime+" time samples of data" ); - if ( nlat .gt. 1 )then - do y = 0, nlat-1 - print( "latitude: "+ nco->latc(y,0) ); - nco->CO2(:,y,0) = (/ ncg->CO2_LBC(:,y) /) * 1.e6; - end do - else - ; make sure all latitudes on file are the same for each time - do itime = 0, ntime-1 - if ( max(ncg->CO2_LBC(itime,:)) .ne. min(ncg->CO2_LBC(itime,:)) )then - print( "Global average, but latitudes are NOT constant" ); - exit - end if - end do - nco->CO2(:,0,0) = (/ ncg->CO2_LBC(:,0) /) * 1.e6; - end if - print( "Average Global First CO2 ppmv value: Date="+nco->date(0)+" CO2="+avg(nco->CO2(0,:,0) ) ); - print( "Average Global Last CO2 ppmv value: Date="+nco->date(ntime-1)+" CO2="+avg(nco->CO2(ntime-1,:,0)) ); - - print( "================================================================================================" ); - print( "Successfully created output historical CO2 file: "+outco2filename); - -end diff --git a/tools/site_and_regional/default_data.cfg b/tools/site_and_regional/default_data.cfg deleted file mode 100644 index 0425aba133..0000000000 --- a/tools/site_and_regional/default_data.cfg +++ /dev/null @@ -1,28 +0,0 @@ -[main] -clmforcingindir = /glade/campaign/cesm/cesmdata/cseg/inputdata - -[datm_gswp3] -dir = atm/datm7/atm_forcing.datm7.GSWP3.0.5d.v1.c170516 -domain = domain.lnd.360x720_gswp3.0v1.c170606.nc -solardir = Solar -precdir = Precip -tpqwdir = TPHWL -solartag = clmforc.GSWP3.c2011.0.5x0.5.Solr. -prectag = clmforc.GSWP3.c2011.0.5x0.5.Prec. -tpqwtag = clmforc.GSWP3.c2011.0.5x0.5.TPQWL. -solarname = CLMGSWP3v1.Solar -precname = CLMGSWP3v1.Precip -tpqwname = CLMGSWP3v1.TPQW - -[surfdat] -dir = lnd/clm2/surfdata_map/release-clm5.0.18 -surfdat_16pft = surfdata_0.9x1.25_hist_16pfts_Irrig_CMIP6_simyr2000_c190214.nc -surfdat_78pft = surfdata_0.9x1.25_hist_78pfts_CMIP6_simyr2000_c190214.nc - -[landuse] -dir = lnd/clm2/surfdata_map/release-clm5.0.18 -landuse_16pft = landuse.timeseries_0.9x1.25_hist_16pfts_Irrig_CMIP6_simyr1850-2015_c190214.nc -landuse_78pft = landuse.timeseries_0.9x1.25_hist_78pfts_CMIP6_simyr1850-2015_c190214.nc - -[domain] -file = share/domains/domain.lnd.fv0.9x1.25_gx1v7.151020.nc diff --git a/tools/site_and_regional/default_data_1850.cfg b/tools/site_and_regional/default_data_1850.cfg new file mode 100644 index 0000000000..47cb71ee87 --- /dev/null +++ b/tools/site_and_regional/default_data_1850.cfg @@ -0,0 +1,27 @@ +[main] +clmforcingindir = /glade/campaign/cesm/cesmdata/inputdata + +[datm_gswp3] +dir = atm/datm7/atm_forcing.datm7.GSWP3.0.5d.v1.c170516 +domain = domain.lnd.360x720_gswp3.0v1.c170606.nc +solardir = Solar +precdir = Precip +tpqwdir = TPHWL +solartag = clmforc.GSWP3.c2011.0.5x0.5.Solr. +prectag = clmforc.GSWP3.c2011.0.5x0.5.Prec. +tpqwtag = clmforc.GSWP3.c2011.0.5x0.5.TPQWL. +solarname = CLMGSWP3v1.Solar +precname = CLMGSWP3v1.Precip +tpqwname = CLMGSWP3v1.TPQW + +[surfdat] +dir = lnd/clm2/surfdata_esmf/ctsm5.2.0 +surfdat_78pft = surfdata_0.9x1.25_hist_1850_78pfts_c240216.nc + +[landuse] +dir = lnd/clm2/surfdata_esmf/ctsm5.2.0 +landuse_78pft = landuse.timeseries_0.9x1.25_SSP2-4.5_1850-2100_78pfts_c240216.nc + +[domain] +file = share/domains/domain.lnd.fv0.9x1.25_gx1v7.151020.nc + diff --git a/python/ctsm/test/testinputs/default_data.cfg b/tools/site_and_regional/default_data_2000.cfg similarity index 56% rename from python/ctsm/test/testinputs/default_data.cfg rename to tools/site_and_regional/default_data_2000.cfg index 0425aba133..0ba7f8758b 100644 --- a/python/ctsm/test/testinputs/default_data.cfg +++ b/tools/site_and_regional/default_data_2000.cfg @@ -15,14 +15,14 @@ precname = CLMGSWP3v1.Precip tpqwname = CLMGSWP3v1.TPQW [surfdat] -dir = lnd/clm2/surfdata_map/release-clm5.0.18 -surfdat_16pft = surfdata_0.9x1.25_hist_16pfts_Irrig_CMIP6_simyr2000_c190214.nc -surfdat_78pft = surfdata_0.9x1.25_hist_78pfts_CMIP6_simyr2000_c190214.nc +dir = lnd/clm2/surfdata_esmf/ctsm5.2.0 +surfdat_16pft = surfdata_0.9x1.25_hist_2000_16pfts_c240216.nc +surfdat_78pft = surfdata_0.9x1.25_hist_2000_78pfts_c240216.nc [landuse] -dir = lnd/clm2/surfdata_map/release-clm5.0.18 -landuse_16pft = landuse.timeseries_0.9x1.25_hist_16pfts_Irrig_CMIP6_simyr1850-2015_c190214.nc -landuse_78pft = landuse.timeseries_0.9x1.25_hist_78pfts_CMIP6_simyr1850-2015_c190214.nc +dir = lnd/clm2/surfdata_esmf/ctsm5.2.0 +landuse_16pft = landuse.timeseries_0.9x1.25_SSP2-4.5_1850-2100_78pfts_c240216.nc +landuse_78pft = landuse.timeseries_0.9x1.25_SSP2-4.5_1850-2100_78pfts_c240216.nc [domain] file = share/domains/domain.lnd.fv0.9x1.25_gx1v7.151020.nc
CLM mkgriddata