diff --git a/cice.setup b/cice.setup index 2fd68cd18..0e574f803 100755 --- a/cice.setup +++ b/cice.setup @@ -838,7 +838,7 @@ EOF endif # from basic script dir to case - foreach file (cice.build cice.settings Makefile ice_in makdep.c setup_run_dirs.csh timeseries.csh timeseries.py) + foreach file (cice.build cice.settings Makefile ice_in makdep.c setup_run_dirs.csh ciceplots.csh ciceplots2d.py timeseries.py) if !(-e ${ICE_SCRIPTS}/$file) then echo "${0}: ERROR, ${ICE_SCRIPTS}/$file not found" exit -1 diff --git a/cicecore/cicedyn/general/ice_forcing.F90 b/cicecore/cicedyn/general/ice_forcing.F90 index b977f54aa..241bf8b5d 100755 --- a/cicecore/cicedyn/general/ice_forcing.F90 +++ b/cicecore/cicedyn/general/ice_forcing.F90 @@ -2276,6 +2276,9 @@ subroutine JRA55_files(yr) enddo if (.not.exists) then + write(nu_diag,*) subname,' atm_data_dir = ',trim(atm_data_dir) + write(nu_diag,*) subname,' atm_data_type_prefix = ',trim(atm_data_type_prefix) + write(nu_diag,*) subname,' atm_data_version = ',trim(atm_data_version) call abort_ice(error_message=subname//' could not find forcing file') endif diff --git a/cicecore/cicedyn/general/ice_init.F90 b/cicecore/cicedyn/general/ice_init.F90 index a7f84e46e..0796efd2d 100644 --- a/cicecore/cicedyn/general/ice_init.F90 +++ b/cicecore/cicedyn/general/ice_init.F90 @@ -164,7 +164,7 @@ subroutine input_data character (len=char_len) :: shortwave, albedo_type, conduct, fbot_xfer_type, & tfrz_option, saltflux_option, frzpnd, atmbndy, wave_spec_type, snwredist, snw_aging_table, & - capping_method, snw_ssp_table + congel_freeze, capping_method, snw_ssp_table logical (kind=log_kind) :: calc_Tsfc, formdrag, highfreq, calc_strair, wave_spec, & sw_redist, calc_dragio, use_smliq_pnd, snwgrain @@ -280,7 +280,7 @@ subroutine input_data highfreq, natmiter, atmiter_conv, calc_dragio, & ustar_min, emissivity, iceruf, iceruf_ocn, & fbot_xfer_type, update_ocn_f, l_mpond_fresh, tfrz_option, & - saltflux_option,ice_ref_salinity,cpl_frazil, & + saltflux_option,ice_ref_salinity,cpl_frazil, congel_freeze, & oceanmixed_ice, restore_ice, restore_ocn, trestore, & precip_units, default_season, wave_spec_type,nfreq, & atm_data_type, ocn_data_type, bgc_data_type, fe_data_type, & @@ -537,6 +537,7 @@ subroutine input_data atmiter_conv = c0 ! ustar convergence criteria precip_units = 'mks' ! 'mm_per_month' or ! 'mm_per_sec' = 'mks' = kg/m^2 s + congel_freeze = 'two-step'! congelation freezing method tfrz_option = 'mushy' ! freezing temp formulation saltflux_option = 'constant' ! saltflux calculation ice_ref_salinity = 4.0_dbl_kind ! Ice reference salinity for coupling @@ -1127,6 +1128,7 @@ subroutine input_data call broadcast_scalar(wave_spec_type, master_task) call broadcast_scalar(wave_spec_file, master_task) call broadcast_scalar(nfreq, master_task) + call broadcast_scalar(congel_freeze, master_task) call broadcast_scalar(tfrz_option, master_task) call broadcast_scalar(saltflux_option, master_task) call broadcast_scalar(ice_ref_salinity, master_task) @@ -2313,6 +2315,7 @@ subroutine input_data if (trim(tfrz_option) == 'constant') then write(nu_diag,1002) ' Tocnfrz = ', Tocnfrz endif + write(nu_diag,1030) ' congel_freeze = ', trim(congel_freeze) if (update_ocn_f) then tmpstr2 = ' : frazil water/salt fluxes included in ocean fluxes' else @@ -2723,7 +2726,7 @@ subroutine input_data aspect_rapid_mode_in=aspect_rapid_mode, dSdt_slow_mode_in=dSdt_slow_mode, & phi_c_slow_mode_in=phi_c_slow_mode, phi_i_mushy_in=phi_i_mushy, conserv_check_in=conserv_check, & wave_spec_type_in = wave_spec_type, wave_spec_in=wave_spec, nfreq_in=nfreq, & - update_ocn_f_in=update_ocn_f, cpl_frazil_in=cpl_frazil, & + update_ocn_f_in=update_ocn_f, cpl_frazil_in=cpl_frazil, congel_freeze_in=congel_freeze, & tfrz_option_in=tfrz_option, kalg_in=kalg, fbot_xfer_type_in=fbot_xfer_type, & saltflux_option_in=saltflux_option, ice_ref_salinity_in=ice_ref_salinity, & Pstar_in=Pstar, Cstar_in=Cstar, iceruf_in=iceruf, iceruf_ocn_in=iceruf_ocn, calc_dragio_in=calc_dragio, & diff --git a/cicecore/cicedyn/infrastructure/io/io_pio2/ice_pio.F90 b/cicecore/cicedyn/infrastructure/io/io_pio2/ice_pio.F90 index 9028fa9b7..94331edf1 100644 --- a/cicecore/cicedyn/infrastructure/io/io_pio2/ice_pio.F90 +++ b/cicecore/cicedyn/infrastructure/io/io_pio2/ice_pio.F90 @@ -236,8 +236,14 @@ subroutine ice_pio_init(mode, filename, File, clobber, fformat, & write(nu_diag,*) subname//' opening file for reading '//trim(filename) endif status = pio_openfile(ice_pio_subsystem, File, pio_iotype, trim(filename), pio_nowrite) - call ice_pio_check( status, subname//' ERROR: Failed to open file '//trim(filename), & - file=__FILE__,line=__LINE__) + if (status /= PIO_NOERR) then + if (my_task == master_task) then + write(nu_diag,*) subname//' opening '//trim(filename)//' as type '//trim(fformat)//' failed, retrying as type cdf1' + endif + status = pio_openfile(ice_pio_subsystem, File, PIO_IOTYPE_NETCDF, trim(filename), pio_nowrite) + call ice_pio_check( status, subname//' ERROR: Failed to open file '//trim(filename), & + file=__FILE__,line=__LINE__) + endif else if(my_task==master_task) then write(nu_diag,*) subname//' ERROR: file not found '//trim(filename) diff --git a/cicecore/cicedyn/infrastructure/io/io_pio2/ice_restart.F90 b/cicecore/cicedyn/infrastructure/io/io_pio2/ice_restart.F90 index fdb9330d2..b487c243d 100644 --- a/cicecore/cicedyn/infrastructure/io/io_pio2/ice_restart.F90 +++ b/cicecore/cicedyn/infrastructure/io/io_pio2/ice_restart.F90 @@ -78,13 +78,8 @@ subroutine init_restart_read(ice_ic) end if File%fh=-1 -! tcraig, including fformat here causes some problems when restart_format=hdf5 -! and reading non hdf5 files with spack built PIO. Excluding the fformat -! argument here defaults the PIO format to cdf1 which then reads -! any netcdf format file fine. call ice_pio_init(mode='read', filename=trim(filename), File=File, & -! fformat=trim(restart_format), rearr=trim(restart_rearranger), & - rearr=trim(restart_rearranger), & + fformat=trim(restart_format), rearr=trim(restart_rearranger), & iotasks=restart_iotasks, root=restart_root, stride=restart_stride, & debug=first_call) diff --git a/cicecore/drivers/nuopc/cmeps/CICE_RunMod.F90 b/cicecore/drivers/nuopc/cmeps/CICE_RunMod.F90 index c2cae81cb..80905080e 100644 --- a/cicecore/drivers/nuopc/cmeps/CICE_RunMod.F90 +++ b/cicecore/drivers/nuopc/cmeps/CICE_RunMod.F90 @@ -191,14 +191,12 @@ subroutine ice_step call init_history_bgc call ice_timer_stop(timer_diags) ! diagnostics/history -#ifdef CESMCOUPLED if (prescribed_ice) then ! read prescribed ice call t_barrierf('cice_run_presc_BARRIER',MPI_COMM_ICE) call t_startf ('cice_run_presc') call ice_prescribed_run(idate, msec) call t_stopf ('cice_run_presc') endif -#endif call step_prep diff --git a/cicecore/drivers/nuopc/cmeps/cice_wrapper_mod.F90 b/cicecore/drivers/nuopc/cmeps/cice_wrapper_mod.F90 index d0aafbb43..db0140b3c 100644 --- a/cicecore/drivers/nuopc/cmeps/cice_wrapper_mod.F90 +++ b/cicecore/drivers/nuopc/cmeps/cice_wrapper_mod.F90 @@ -2,7 +2,7 @@ module cice_wrapper_mod #ifdef CESMCOUPLED use perf_mod , only : t_startf, t_stopf, t_barrierf - use shr_file_mod , only : shr_file_getlogunit, shr_file_setlogunit + use shr_log_mod , only : shr_log_getlogunit, shr_log_setlogunit use ice_kinds_mod , only : dbl_kind, int_kind, char_len, char_len_long @@ -72,7 +72,7 @@ subroutine ufs_logfhour(msg,hour) real(dbl_kind), intent(in) :: hour character(len=char_len) :: filename integer(int_kind) :: nunit - write(filename,'(a,i3.3)')'log.ice.f',int(hour) + write(filename,'(a,i4.4)')'log.ice.f',int(hour) open(newunit=nunit,file=trim(filename)) write(nunit,'(a)')'completed: cice' write(nunit,'(a,f10.3)')'forecast hour:',hour @@ -82,12 +82,12 @@ end subroutine ufs_logfhour ! Define stub routines that do nothing - they are just here to avoid ! having cppdefs in the main program - subroutine shr_file_setLogUnit(nunit) + subroutine shr_log_setLogUnit(nunit) integer, intent(in) :: nunit - end subroutine shr_file_setLogUnit - subroutine shr_file_getLogUnit(nunit) + end subroutine shr_log_setLogUnit + subroutine shr_log_getLogUnit(nunit) integer, intent(in) :: nunit - end subroutine shr_file_getLogUnit + end subroutine shr_log_getLogUnit subroutine t_startf(string) character(len=*) :: string end subroutine t_startf diff --git a/cicecore/drivers/nuopc/cmeps/ice_comp_nuopc.F90 b/cicecore/drivers/nuopc/cmeps/ice_comp_nuopc.F90 index 3423fbf36..4c4be8308 100644 --- a/cicecore/drivers/nuopc/cmeps/ice_comp_nuopc.F90 +++ b/cicecore/drivers/nuopc/cmeps/ice_comp_nuopc.F90 @@ -38,7 +38,7 @@ module ice_comp_nuopc use icepack_intfc , only : icepack_init_orbit, icepack_init_parameters, icepack_query_orbit use icepack_intfc , only : icepack_query_tracer_flags, icepack_query_parameters use cice_wrapper_mod , only : t_startf, t_stopf, t_barrierf - use cice_wrapper_mod , only : shr_file_getlogunit, shr_file_setlogunit + use cice_wrapper_mod , only : shr_log_getlogunit, shr_log_setlogunit use cice_wrapper_mod , only : ufs_settimer, ufs_logtimer, ufs_file_setlogunit, wtime #ifdef CESMCOUPLED use shr_const_mod @@ -95,6 +95,7 @@ module ice_comp_nuopc logical :: profile_memory = .false. logical :: mastertask logical :: runtimelog = .false. + logical :: restart_eor = .false. !End of run restart flag integer :: start_ymd ! Start date (YYYYMMDD) integer :: start_tod ! start time of day (s) integer :: curr_ymd ! Current date (YYYYMMDD) @@ -316,6 +317,12 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) write(logmsg,*) runtimelog call ESMF_LogWrite('CICE_cap:RunTimeLog = '//trim(logmsg), ESMF_LOGMSG_INFO) + call NUOPC_CompAttributeGet(gcomp, name="write_restart_at_endofrun", value=cvalue, isPresent=isPresent, isSet=isSet, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + if (isPresent .and. isSet) then + if (trim(cvalue) .eq. '.true.') restart_eor = .true. + endif + !---------------------------------------------------------------------------- ! generate local mpi comm !---------------------------------------------------------------------------- @@ -497,7 +504,7 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) ! Note that sets the nu_diag module variable in ice_fileunits ! Set the nu_diag_set flag so it's not reset later - call shr_file_setLogUnit (shrlogunit) + call shr_log_setLogUnit (shrlogunit) call ufs_file_setLogUnit('./log.ice.timer',nu_timer,runtimelog) call NUOPC_CompAttributeGet(gcomp, name="diro", value=cvalue, & @@ -885,7 +892,7 @@ subroutine InitializeRealize(gcomp, importState, exportState, clock, rc) ! Prescribed ice initialization !----------------------------------------------------------------- - call ice_prescribed_init(clock, ice_mesh, rc) + call ice_prescribed_init(gcomp, clock, ice_mesh, rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return #ifdef CESMCOUPLED @@ -1067,8 +1074,8 @@ subroutine ModelAdvance(gcomp, rc) ! Reset shr logging to my log file !-------------------------------- - call shr_file_getLogUnit (shrlogunit) - call shr_file_setLogUnit (nu_diag) + call shr_log_getLogUnit (shrlogunit) + call shr_log_setLogUnit (nu_diag) !-------------------------------- ! Query the Component for its clock, importState and exportState @@ -1139,6 +1146,8 @@ subroutine ModelAdvance(gcomp, rc) call ESMF_ClockGetAlarm(clock, alarmname='alarm_restart', alarm=alarm, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return + force_restart_now = .false. + if (ESMF_AlarmIsRinging(alarm, rc=rc)) then if (ChkErr(rc,__LINE__,u_FILE_u)) return force_restart_now = .true. @@ -1152,8 +1161,18 @@ subroutine ModelAdvance(gcomp, rc) write(restart_date,"(i4.4,a,i2.2,a,i2.2,a,i5.5)") yy, '-', mm, '-',dd,'-',tod write(restart_filename,'(4a)') trim(restart_dir), trim(restart_file), '.', trim(restart_date) - else - force_restart_now = .false. + endif + + ! Handle end of run restart + if (restart_eor) then + call ESMF_ClockGetAlarm(clock, alarmname='alarm_stop', alarm=alarm, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + if (ESMF_AlarmIsRinging(alarm, rc=rc)) then + if (ChkErr(rc,__LINE__,u_FILE_u)) return + force_restart_now = .true. + call ESMF_AlarmRingerOff( alarm, rc=rc ) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + endif endif !-------------------------------- @@ -1207,7 +1226,7 @@ subroutine ModelAdvance(gcomp, rc) end if ! reset shr logging to my original values - call shr_file_setLogUnit (shrlogunit) + call shr_log_setLogUnit (shrlogunit) !-------------------------------- ! stop timers and print timer info diff --git a/cicecore/drivers/nuopc/cmeps/ice_import_export.F90 b/cicecore/drivers/nuopc/cmeps/ice_import_export.F90 index 47abb0373..6b539a051 100644 --- a/cicecore/drivers/nuopc/cmeps/ice_import_export.F90 +++ b/cicecore/drivers/nuopc/cmeps/ice_import_export.F90 @@ -1495,6 +1495,7 @@ subroutine SetScalarField(field, flds_scalar_name, flds_scalar_num, rc) ! local variables type(ESMF_Distgrid) :: distgrid type(ESMF_Grid) :: grid + real(ESMF_KIND_R8), pointer :: fldptr2d(:,:) character(len=*), parameter :: subname='(ice_import_export:SetScalarField)' ! ---------------------------------------------- @@ -1511,6 +1512,11 @@ subroutine SetScalarField(field, flds_scalar_name, flds_scalar_num, rc) ungriddedLBound=(/1/), ungriddedUBound=(/flds_scalar_num/), gridToFieldMap=(/2/), rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return + ! initialize fldptr to zero + call ESMF_FieldGet(field, farrayPtr=fldptr2d, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + fldptr2d(:,:) = 0.0 + end subroutine SetScalarField end subroutine fldlist_realize diff --git a/cicecore/drivers/nuopc/cmeps/ice_prescribed_mod.F90 b/cicecore/drivers/nuopc/cmeps/ice_prescribed_mod.F90 index b46f22ff7..2436783bc 100644 --- a/cicecore/drivers/nuopc/cmeps/ice_prescribed_mod.F90 +++ b/cicecore/drivers/nuopc/cmeps/ice_prescribed_mod.F90 @@ -6,34 +6,20 @@ module ice_prescribed_mod ! prescribed. Air/ice fluxes are computed to get surface temperature, ! Ice/ocean fluxes are set to zero, and ice dynamics are not calculated. ! Regridding and data cycling capabilities are included. + + ! Note (8/8/2024): This code is dependent on CDEPS (to input ice data). + ! In the interests of cleaner code, drivers/nuopc/cmeps now is too. + ! If problematic, please see https://github.com/CICE-Consortium/CICE/pull/964 for alternatives. - use ESMF, only : ESMF_Clock, ESMF_Mesh, ESMF_SUCCESS, ESMF_FAILURE + use ESMF, only : ESMF_GridComp, ESMF_Clock, ESMF_Mesh, ESMF_SUCCESS, ESMF_FAILURE use ESMF, only : ESMF_LogFoundError, ESMF_LOGERR_PASSTHRU, ESMF_Finalize, ESMF_END_ABORT -#ifndef CESMCOUPLED - - use ice_kinds_mod - implicit none - private ! except - public :: ice_prescribed_init ! initialize input data stream - logical(kind=log_kind), parameter, public :: prescribed_ice = .false. ! true if prescribed ice -contains - ! This is a stub routine for now - subroutine ice_prescribed_init(clock, mesh, rc) - type(ESMF_Clock) , intent(in) :: clock - type(ESMF_Mesh) , intent(in) :: mesh - integer , intent(out) :: rc - ! do nothing - rc = ESMF_SUCCESS - end subroutine ice_prescribed_init - -#else - use ice_kinds_mod use shr_nl_mod , only : shr_nl_find_group_name use dshr_strdata_mod , only : shr_strdata_type, shr_strdata_print use dshr_strdata_mod , only : shr_strdata_init_from_inline, shr_strdata_advance use dshr_methods_mod , only : dshr_fldbun_getfldptr + use dshr_mod , only : dshr_pio_init use ice_broadcast use ice_communicate , only : my_task, master_task, MPI_COMM_ICE use ice_fileunits @@ -43,7 +29,7 @@ end subroutine ice_prescribed_init use ice_blocks , only : nx_block, ny_block, block, get_block use ice_domain , only : nblocks, distrb_info, blocks_ice use ice_grid , only : TLAT, TLON, hm, tmask, tarea, grid_type, ocn_gridcell_frac - use ice_calendar , only : idate, calendar_type + use ice_calendar , only : idate, msec, calendar_type use ice_arrays_column , only : hin_max use ice_read_write use ice_exit , only: abort_ice @@ -74,13 +60,17 @@ end subroutine ice_prescribed_init contains !=============================================================================== - subroutine ice_prescribed_init(clock, mesh, rc) + subroutine ice_prescribed_init(gcomp, clock, mesh, rc) ! Prescribed ice initialization - include 'mpif.h' +#ifndef SERIAL_REMOVE_MPI + !TODO: add 1d character array to cicecore/cicedyn/infrastructure/comm/mpi/ice_broadcast.F90 + use mpi ! MPI Fortran module +#endif ! input/output parameters + type(ESMF_GridComp) , intent(in) :: gcomp type(ESMF_Clock) , intent(in) :: clock type(ESMF_Mesh) , intent(in) :: mesh integer , intent(out) :: rc @@ -93,6 +83,7 @@ subroutine ice_prescribed_init(clock, mesh, rc) character(len=char_len_long) :: stream_dataFiles(nFilesMaximum) character(len=char_len_long) :: stream_varname character(len=char_len_long) :: stream_mapalgo + character(len=char_len_long) :: stream_taxmode integer(kind=int_kind) :: stream_yearfirst ! first year in stream to use integer(kind=int_kind) :: stream_yearlast ! last year in stream to use integer(kind=int_kind) :: stream_yearalign ! align stream_year_first @@ -110,6 +101,7 @@ subroutine ice_prescribed_init(clock, mesh, rc) stream_varname , & stream_datafiles, & stream_mapalgo, & + stream_taxmode, & stream_yearalign, & stream_yearfirst , & stream_yearlast @@ -125,6 +117,7 @@ subroutine ice_prescribed_init(clock, mesh, rc) stream_meshfile = ' ' stream_datafiles(:) = ' ' stream_mapalgo = 'bilinear' + stream_taxmode = 'cycle' ! read namelist on master task if (my_task == master_task) then @@ -155,6 +148,7 @@ subroutine ice_prescribed_init(clock, mesh, rc) call broadcast_scalar(stream_yearlast , master_task) call broadcast_scalar(stream_meshfile , master_task) call broadcast_scalar(stream_mapalgo , master_task) + call broadcast_scalar(stream_taxmode , master_task) call broadcast_scalar(stream_varname , master_task) call mpi_bcast(stream_dataFiles, len(stream_datafiles(1))*NFilesMaximum, MPI_CHARACTER, 0, MPI_COMM_ICE, ierr) @@ -172,12 +166,18 @@ subroutine ice_prescribed_init(clock, mesh, rc) write(nu_diag,F00) ' stream_meshfile = ',trim(stream_meshfile) write(nu_diag,F00) ' stream_varname = ',trim(stream_varname) write(nu_diag,F00) ' stream_mapalgo = ',trim(stream_mapalgo) + write(nu_diag,F00) ' stream_taxmode = ',trim(stream_taxmode) do n = 1,nFile write(nu_diag,F00) ' stream_datafiles = ',trim(stream_dataFiles(n)) end do write(nu_diag,*) ' ' endif +#ifndef CESMCOUPLED + !CESM does this elsewhere + call dshr_pio_init(gcomp, sdat, nu_diag, rc) +#endif + ! initialize sdat call shr_strdata_init_from_inline(sdat, & my_task = my_task, & @@ -189,13 +189,13 @@ subroutine ice_prescribed_init(clock, mesh, rc) stream_lev_dimname = 'null', & stream_mapalgo = trim(stream_mapalgo), & stream_filenames = stream_datafiles(1:nfile), & - stream_fldlistFile = (/'ice_cov'/), & - stream_fldListModel = (/'ice_cov'/), & + stream_fldlistFile = (/trim(stream_varname)/), & + stream_fldListModel = (/trim(stream_varname)/), & stream_yearFirst = stream_yearFirst, & stream_yearLast = stream_yearLast, & stream_yearAlign = stream_yearAlign , & stream_offset = 0, & - stream_taxmode = 'cycle', & + stream_taxmode = trim(stream_taxmode), & stream_dtlimit = 1.5_dbl_kind, & stream_tintalgo = 'linear', & rc = rc) @@ -211,6 +211,11 @@ subroutine ice_prescribed_init(clock, mesh, rc) hin_max(1) = 999._dbl_kind end if +#ifndef CESMCOUPLED + ! If need initial cice values for coupling + call ice_prescribed_run(idate, msec) +#endif + end if ! end of if prescribed ice mode end subroutine ice_prescribed_init @@ -489,6 +494,4 @@ subroutine ice_prescribed_phys() end subroutine ice_prescribed_phys -#endif - end module ice_prescribed_mod diff --git a/cicecore/drivers/nuopc/cmeps/ice_shr_methods.F90 b/cicecore/drivers/nuopc/cmeps/ice_shr_methods.F90 index 1144568b4..65596d822 100644 --- a/cicecore/drivers/nuopc/cmeps/ice_shr_methods.F90 +++ b/cicecore/drivers/nuopc/cmeps/ice_shr_methods.F90 @@ -23,7 +23,7 @@ module ice_shr_methods use ice_kinds_mod, only : r8 => dbl_kind, cl=>char_len_long, cs=>char_len use ice_exit , only : abort_ice #ifdef CESMCOUPLED - use shr_file_mod , only : shr_file_setlogunit, shr_file_getLogUnit + use shr_log_mod , only : shr_log_setlogunit #endif implicit none @@ -165,7 +165,7 @@ subroutine set_component_logging(gcomp, mastertask, logunit, shrlogunit, rc) endif #ifdef CESMCOUPLED - call shr_file_setLogUnit (logunit) + call shr_log_setLogUnit (logunit) #endif end subroutine set_component_logging diff --git a/configuration/scripts/ciceplots.csh b/configuration/scripts/ciceplots.csh new file mode 100755 index 000000000..43528b33e --- /dev/null +++ b/configuration/scripts/ciceplots.csh @@ -0,0 +1,56 @@ +#!/bin/csh -f + +source ${MODULESHOME}/init/csh + +# User defined stuff +# Set case and case directory +# Set files, notes, fstr, and fields + +set case = "CICE6.5.1" +set casedir = "/glade/derecho/scratch/tcraig/CICE_RUNS/cgx1proda" + +# setup plots + +set histdir = "${casedir}/history" + +set files = ("${histdir}/iceh.2012-03.nc" \ + "${histdir}/iceh.2012-09.nc" ) +set notes = ("2012 March Mean" \ + "2012 Sept Mean" ) +set fstrs = ("Mar12" \ + "Sep12" ) + +set fields = ("aice" "hi" "hs") + +#conda config --add channels conda-forge +#conda config --set channel_priority strict +#conda search basemap --channel conda-forge +#conda create -p /glade/u/home/tcraig/conda/envs/basemap -c conda-forge basemap=1.4.1 basemap-data basemap-data-hires netCDF4 + +module load conda +source ${NCAR_ROOT_CONDA}/etc/profile.d/conda.csh + +conda activate /glade/u/home/tcraig/conda/envs/basemap + +echo " " +echo " " + +echo ./timeseries.py \"${casedir}\" --case \"${case}\" --grid +./timeseries.py "${casedir}" --case "${case}" --grid + +echo " " + +set cnt = 0 +while ($cnt < ${#files}) + @ cnt = $cnt + 1 + set file = "${files[$cnt]}" + set note = "${notes[$cnt]}" + set fstr = "${fstrs[$cnt]}" + foreach field ($fields) + echo ./ciceplots2d.py \"$field\" \"$file\" \"$case\" \"$note\" \"$fstr\" + ./ciceplots2d.py "$field" "$file" "$case" "$note" "$fstr" + end +end + +echo "DONE" + diff --git a/configuration/scripts/ciceplots2d.py b/configuration/scripts/ciceplots2d.py new file mode 100755 index 000000000..2ad73e66f --- /dev/null +++ b/configuration/scripts/ciceplots2d.py @@ -0,0 +1,148 @@ +#!/usr/bin/env python3 + +#Importing the necessary libraries +import sys +import os +import numpy as np +from netCDF4 import Dataset +import matplotlib as mpl +import matplotlib.pyplot as plt +from mpl_toolkits.basemap import Basemap + +if len(sys.argv) != 6: + print("ciceplots.py requires 5 arguments") + print(" 1. field name in file, ie. \"aice\"") + print(" 2. cice history file full path, ie. \"/glade/scratch/user/case/history/iceh.2012-03.nc\"") + print(" 3. case name, used to annotate plot, ie. \"CICE6.5.1\"") + print(" 4. notes, used to annotate plot, ie. 2012 \"March Mean\"") + print(" 5. file string, use to create unique png filenames, ie. \"Mar12\"") + quit() + +field = sys.argv[1] +pathf = sys.argv[2] +casen = sys.argv[3] +notes = sys.argv[4] +fstr = sys.argv[5] +fname = os.path.basename(pathf) +title = field + " " + notes +cfnam = casen + " " + fname +#print("field = ",field) +#print("pathf = ",pathf) +#print("casen = ",casen) +#print("notes = ",notes) +#print("fname = ",fname) +#print("title = ",title) +#print("cfnam = ",cfnam) + +#Reading the netCDF file +data = Dataset(pathf,'r') +#print (data) + +lons = data.variables['TLON'][:,:] +lats = data.variables['TLAT'][:,:] +var1 = data.variables[field][:,:,:] +var1 = var1[0,:,:] +var1[ var1==0.00 ] = np.nan +#mask = data.variables['tmask'][:,:] +#mask[ mask>0.5 ] = np.nan + +#print("lons.shape = ",lons.shape) +#print("var1.shape = ",var1.shape) + +# Lon/Lat Projection + +#print("Plot global") +#m = Basemap(projection='cyl',llcrnrlat=-90,urcrnrlat=90, +# llcrnrlon=0,urcrnrlon=360,resolution='c') +m = Basemap(projection='cyl',llcrnrlat=-90,urcrnrlat=90, + llcrnrlon=0,urcrnrlon=360,resolution='l') +fig, ax = plt.subplots() +#plt.figure(figsize=(6,4)) +m.drawcoastlines(linewidth=0.2) +m.fillcontinents(color='black',lake_color='white') +#draw parallels and meridians. +m.drawparallels(np.arange(-60.,61.,30.),labels=[1,0,0,0]) +m.drawmeridians(np.arange(0.,361.,45.),labels=[1,0,0,1]) +#draw map boundary +m.drawmapboundary(fill_color='white') +#setting colorbar +cmap = plt.get_cmap('jet') +barticks = None +norm = "linear" +if field in ['hi']: + bounds = np.arange(0,2.05,0.1) + bounds = np.append(bounds,[2.25,2.5,2.75,3.0,3.25,3.5,3.75,4.0]) + norm = mpl.colors.BoundaryNorm(bounds,cmap.N,extend='max') + barticks=[0,0.5,1.0,1.5,2.0,2.5,3.0,3.5,4.0] +if field in ['hs']: + bounds = np.arange(0,1.02,0.05) + bounds = np.append(bounds,[1.5,2.0,2.5,3.0,3.5,4.0]) + norm = mpl.colors.BoundaryNorm(bounds,cmap.N,extend='max') + barticks=[0,0.25,0.5,0.75,1.0,2.0,3.0,4.0] +#matplotlib scatter-plot +m.scatter(lons,lats,c=var1,cmap=cmap,marker='o',s=0.2,norm=norm) +m.colorbar(label=field, ticks=barticks) +plt.rcParams["figure.dpi"] = 300 +plt.title(title) +plt.text(x=0.0,y=-0.1,s=cfnam,transform=ax.transAxes,horizontalalignment='left',verticalalignment='top',fontsize='x-small') +oname = field + "_gl_" + fstr + ".png" +print('Saving file to ',oname) +plt.savefig(oname) +#plt.show() +plt.close() + +# North Polar Stereographic Projection + +#print("Plot NH") +#m = Basemap(projection='npstere',boundinglat=45,lon_0=-45,resolution='c') +m = Basemap(projection='npstere',boundinglat=45,lon_0=-45,resolution='l') +fig, ax = plt.subplots() +#plt.figure(figsize=(6,4)) +m.drawcoastlines(linewidth=0.2) +m.fillcontinents(color='black',lake_color='white') +# draw parallels and meridians. +m.drawparallels(np.arange(-60.,61.,30.),labels=[0,0,0,0]) +m.drawmeridians(np.arange(0.,361.,45.),labels=[0,0,0,0]) +m.drawmapboundary(fill_color='white') +#setting colorbar (set above) +m.scatter(lons,lats,c=var1,cmap=cmap,marker='o',s=0.2,latlon=True,norm=norm) +#m.colorbar(label=field) +m.colorbar(label=field, ticks=barticks) +plt.rcParams["figure.dpi"] = 300 +plt.title (title) +plt.text(x=0.0,y=-0.02,s=cfnam,transform=ax.transAxes,horizontalalignment='left',verticalalignment='top',fontsize='x-small') +oname = field + "_nh_" + fstr + ".png" +print('Saving file to ',oname) +plt.savefig(oname) +#plt.show() +plt.close() + +# South Polar Stereographic Projection + +#print("Plot SH") +#m = Basemap(projection='npstere',boundinglat=45,lon_0=-45,resolution='c') +m = Basemap(projection='spstere',boundinglat=-45,lon_0=180,resolution='l') +fig, ax = plt.subplots() +#plt.figure(figsize=(6,4)) +m.drawcoastlines(linewidth=0.2) +m.fillcontinents(color='black',lake_color='white') +# draw parallels and meridians. +m.drawparallels(np.arange(-60.,61.,30.),labels=[0,0,0,0]) +m.drawmeridians(np.arange(0.,361.,45.),labels=[0,0,0,0]) +m.drawmapboundary(fill_color='white') +#setting colorbar (set above) +m.scatter(lons,lats,c=var1,cmap=cmap,marker='o',s=0.2,latlon=True,norm=norm) +#m.colorbar(label=field) +m.colorbar(label=field, ticks=barticks) +plt.rcParams["figure.dpi"] = 300 +plt.title (title) +plt.text(x=0.0,y=-0.02,s=cfnam,transform=ax.transAxes,horizontalalignment='left',verticalalignment='top',fontsize='x-small') +oname = field + "_sh_" + fstr + ".png" +print('Saving file to ',oname) +plt.savefig(oname) +#plt.show() +plt.close() + +#print("Done") +quit() + diff --git a/configuration/scripts/ice_in b/configuration/scripts/ice_in index ad29e05ce..d9215de60 100644 --- a/configuration/scripts/ice_in +++ b/configuration/scripts/ice_in @@ -270,6 +270,7 @@ fbot_xfer_type = 'constant' update_ocn_f = .false. l_mpond_fresh = .false. + congel_freeze = 'two-step' tfrz_option = 'mushy' saltflux_option = 'constant' ice_ref_salinity = 4.0 diff --git a/configuration/scripts/machines/Macros.izumi_nag b/configuration/scripts/machines/Macros.izumi_nag index c12edb904..9265c9de1 100644 --- a/configuration/scripts/machines/Macros.izumi_nag +++ b/configuration/scripts/machines/Macros.izumi_nag @@ -3,7 +3,7 @@ #============================================================================== CPP := /usr/bin/cpp -CPPDEFS := -DFORTRANUNDERSCORE -DNO_R16 $(ICE_CPPDEFS) +CPPDEFS := -DFORTRANUNDERSCORE -DNO_R16 -DNO_CDF5 $(ICE_CPPDEFS) CFLAGS := -c FIXEDFLAGS := -fixed diff --git a/configuration/scripts/machines/env.chicoma_intel b/configuration/scripts/machines/env.chicoma_intel index a324ec0fe..1f8f8ac8b 100644 --- a/configuration/scripts/machines/env.chicoma_intel +++ b/configuration/scripts/machines/env.chicoma_intel @@ -64,7 +64,7 @@ setenv ICE_MACHINE_WKDIR /lustre/scratch5/$user/CICE_RUNS setenv ICE_MACHINE_INPUTDATA /usr/projects/climate/eclare/DATA/Consortium setenv ICE_MACHINE_BASELINE /lustre/scratch5/$user/CICE_BASELINE setenv ICE_MACHINE_SUBMIT "sbatch " -setenv ICE_MACHINE_ACCT t23_cice +setenv ICE_MACHINE_ACCT t24_cice setenv ICE_MACHINE_QUEUE "debug" setenv ICE_MACHINE_TPNODE 128 # tasks per node setenv ICE_MACHINE_BLDTHRDS 12 diff --git a/configuration/scripts/machines/environment.yml b/configuration/scripts/machines/environment.yml index 30ed1e148..119bf7ea0 100644 --- a/configuration/scripts/machines/environment.yml +++ b/configuration/scripts/machines/environment.yml @@ -15,6 +15,9 @@ dependencies: - matplotlib-base - cartopy - netcdf4 + - basemap=1.4.1 + - basemap-data + - basemap-data-hires # Python dependencies for building the HTML documentation - sphinx - sphinxcontrib-bibtex diff --git a/configuration/scripts/options/set_nml.congel b/configuration/scripts/options/set_nml.congel new file mode 100644 index 000000000..d61042cbd --- /dev/null +++ b/configuration/scripts/options/set_nml.congel @@ -0,0 +1,2 @@ + congel_freeze = 'one-step' + diff --git a/configuration/scripts/options/set_nml.run8year b/configuration/scripts/options/set_nml.run8year new file mode 100644 index 000000000..1515fa7c9 --- /dev/null +++ b/configuration/scripts/options/set_nml.run8year @@ -0,0 +1,7 @@ +npt_unit = 'y' +npt = 8 +dumpfreq = 'y' +dumpfreq_n = 1 +diagfreq = 24 +histfreq = 'm','x','x','x','x' + diff --git a/configuration/scripts/tests/base_suite.ts b/configuration/scripts/tests/base_suite.ts index 3a18d8548..3f34da8a2 100644 --- a/configuration/scripts/tests/base_suite.ts +++ b/configuration/scripts/tests/base_suite.ts @@ -27,6 +27,7 @@ restart gx3 8x2 alt06 restart gx3 8x3 alt07 restart gx3 16x2 snicar restart gx3 12x2 snicartest +restart gx3 8x2 congel restart gx3 8x3 saltflux restart gx3 18x2 debug,maskhalo restart gx3 6x2 alt01,debug,short @@ -37,6 +38,7 @@ smoke gx3 4x4 alt04,debug,short smoke gx3 4x4 alt05,debug,short smoke gx3 8x2 alt06,debug,short smoke gx3 8x3 alt07,debug,short +smoke gx3 8x2 congel,debug,short smoke gx3 16x2 snicar,debug,short smoke gx3 12x2 snicartest,debug,short smoke gx3 10x2 debug,diag1,run5day,gx3sep2 diff --git a/configuration/scripts/tests/prod_suite.ts b/configuration/scripts/tests/prod_suite.ts index 877fa1ce6..5e62e94ea 100644 --- a/configuration/scripts/tests/prod_suite.ts +++ b/configuration/scripts/tests/prod_suite.ts @@ -1,6 +1,6 @@ # Test Grid PEs Sets BFB-compare qcchk gx3 72x1 qc,qcchk,medium qcchk_gx3_72x1_medium_qc_qcchk qcchk gx1 144x1 qc,qcchk,medium -smoke gx1 144x2 gx1prod,long,run10year +smoke gx1 128x2 gx1prod,long,run8year qcchk gx3 72x1 qc,qcchkf,medium,alt02 qcchk_gx3_72x1_medium_qc_qcchk qcchk gx3 72x1 qc,qcchk,dt3456s,medium qcchk_gx3_72x1_medium_qc_qcchk diff --git a/configuration/scripts/timeseries.csh b/configuration/scripts/timeseries.csh deleted file mode 100755 index b6b3fcf2e..000000000 --- a/configuration/scripts/timeseries.csh +++ /dev/null @@ -1,129 +0,0 @@ -#!/bin/csh - -# Check to see if test case directory was passed -if ( $1 == "-h" ) then - echo "To generate timeseries plots, this script can be passed a directory" - echo "containing a logs/ subdirectory, or it can be run in the directory with" - echo "the log files, without being passed a directory." - echo "Example: ./timeseries.csh ./annual_gx3_conrad_4x1.t00" - echo "Example: ./timeseries.csh" - echo "It will pull the diagnostic data from the most recently modified log file." - exit -1 -endif -set basename = `echo $1 | sed -e 's#/$##' | sed -e 's/^\.\///'` - -# Set x-axis limits - # Manually set x-axis limits -#set xrange = 'set xrange ["19980101":"19981231"]' - # Let gnuplot determine x-axis limits -set xrange = '' - -# Determine if BASELINE dataset exists -if ( $1 == "" ) then -set basefile_dir = "IGNORE" -else -source $1/cice.settings -set basefile_dir = "$ICE_BASELINE/$ICE_BASECOM/$ICE_TESTNAME" -endif - -if ( -d $basefile_dir ) then - set num_basefile = `ls $basefile_dir | grep cice.runlog | wc -l` - if ( $num_basefile > 0 ) then - set baseline_exists = 1 - foreach file ($basefile_dir/cice.runlog.*) - set base_logfile = $file - end - else - set baseline_exists = 0 - endif -else - set baseline_exists = 0 -endif - -set fieldlist=("total ice area (km^2)" \ - "total ice extent(km^2)" \ - "total ice volume (m^3)" \ - "total snw volume (m^3)" \ - "rms ice speed (m/s)" ) - -# Get the filename for the latest log -if ( $1 == "" ) then -foreach file (./cice.runlog.*) - set logfile = $file -end -else -foreach file ($1/logs/cice.runlog.*) - set logfile = $file -end -endif - -# Loop through each field and create the plot -foreach field ($fieldlist:q) - # Add backslashes before (, ), and ^ for grep searches - set search_name = "`echo '$field' | sed 's/(/\\(/' | sed 's/)/\\)/' | sed 's/\^/\\^/'`" - set fieldname = `echo "$field" | sed -e 's/([^()]*)//g'` - set search = "'$search_name'\|istep1" - rm -f data.txt - foreach line ("`egrep $search $logfile`") - if ("$line" =~ *"istep1"*) then - set argv = ( $line ) - set date = $4 - @ hour = ( $6 / 3600 ) - else - set data1 = `echo $line | rev | cut -d ' ' -f2 | rev` - set data2 = `echo $line | rev | cut -d ' ' -f1 | rev` - echo "$date-$hour,$data1,$data2" >> data.txt - endif - end - set format = "%Y%m%d-%H" - - set output = `echo $fieldname | sed 's/ /_/g'` - set output = "${output}_${ICE_CASENAME}.png" - - echo "Plotting data for '$fieldname' and saving to $output" - -# Call the plotting routine, which uses the data in the data.txt file -gnuplot << EOF > $output -# Plot style -set style data points - -set datafile separator "," - -# Term type and background color, canvas size -set terminal png size 1920,960 - -# x-axis -set xdata time -set timefmt "$format" -set format x "%Y/%m/%d" - -# Axis tick marks -set xtics rotate - -set title "$field (Diagnostic Output)" -set ylabel "$field" -set xlabel "Simulation Day" - -set key left top - -# Set x-axlis limits -$xrange - -if ( $baseline_exists == 1 ) \ - plot "data_baseline.txt" using (timecolumn(1)):2 with lines lw 2 lt 2 lc 2 title \ - "Arctic - Baseline", \ - "" using (timecolumn(1)):3 with lines lw 2 lt 2 lc 5 title "Antarctic - Baseline", \ - "data.txt" using (timecolumn(1)):2 with lines lw 2 lt 1 lc 1 title "Arctic", \ - "" using (timecolumn(1)):3 with lines lw 2 lt 1 lc 3 title "Antarctic"; \ -else \ - plot "data.txt" using (timecolumn(1)):2 with lines lw 2 lt 1 lc 1 title "Arctic", \ - "" using (timecolumn(1)):3 with lines lw 2 lt 1 lc 3 title "Antarctic" \ - -EOF - -# Delete the data file -rm -f data.txt -if ( $baseline_exists ) then - rm -f data_baseline.txt -endif -end diff --git a/configuration/scripts/timeseries.py b/configuration/scripts/timeseries.py index 2c36cea73..c53106071 100755 --- a/configuration/scripts/timeseries.py +++ b/configuration/scripts/timeseries.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 ''' This script generates timeseries plots of CICE diagnostic output. @@ -51,16 +51,16 @@ def get_data(logfile,field): logger.debug('Extracting data for {}'.format(field)) # Build the regular expression to extract the data - field_regex = field.replace('(','\(').replace('^','\^').replace(')','\)') - number_regex = '[-+]?\d+\.?\d+([eE][-+]?\d+)?' - my_regex = '^{}\s+=\s+({})\s+({})'.format(field_regex,number_regex,number_regex) + field_regex = field.replace('(','\\(').replace('^','\\^').replace(')','\\)') + number_regex = r'[-+]?\d+\.?\d+([eE][-+]?\d+)?' + my_regex = r'^{}\s+=\s+({})\s+({})'.format(field_regex,number_regex,number_regex) dtg = [] arctic = [] antarctic = [] with open(logfile) as f: for line in f.readlines(): - m1 = re.search('istep1:\s+(\d+)\s+idate:\s+(\d+)\s+sec:\s+(\d+)', line) + m1 = re.search(r'istep1:\s+(\d+)\s+idate:\s+(\d+)\s+sec:\s+(\d+)', line) if m1: # Extract the current date-time group from the file date = m1.group(2) @@ -83,6 +83,11 @@ def get_data(logfile,field): antarctic.append(float(m.group(3))) logger.debug(' Arctic = {}, Antarctic = {}'.format(arctic[-1], antarctic[-1])) + # remove first few elements of dtg + if len(dtg) > len(arctic): + stind = len(dtg) - len(arctic) + dtg = dtg[stind:] + return dtg, arctic, antarctic, expon def latexit(string): @@ -90,15 +95,17 @@ def latexit(string): return (s.replace(')','$)',1))[::-1] def plot_timeseries(log, field, dtg, arctic, antarctic, expon, dtg_base=None, arctic_base=None, \ - antarctic_base=None, base_dir=None, grid=False): + antarctic_base=None, base_dir=None, grid=False, casename=None, base_casename=None): ''' Plot the timeseries data from the CICE log file ''' import re - casename = re.sub(r"/logs", "", os.path.abspath(log).rstrip('/')).split('/')[-1] + if casename is None: + casename = re.sub(r"/logs", "", os.path.abspath(log).rstrip('/')).split('/')[-1] if base_dir: - base_casename = re.sub(r"/logs", "", os.path.abspath(base_dir).rstrip('/')).split('/')[-1] + if base_casename is None: + base_casename = re.sub(r"/logs", "", os.path.abspath(base_dir).rstrip('/')).split('/')[-1] # Load the plotting libraries, but set the logging level for matplotlib # to WARNING so that matplotlib debugging info is not printed when running @@ -108,7 +115,8 @@ def plot_timeseries(log, field, dtg, arctic, antarctic, expon, dtg_base=None, ar import matplotlib.dates as mdates import matplotlib.ticker as ticker - fig = plt.figure(figsize=(12,8)) +# fig = plt.figure(figsize=(12,8)) + fig = plt.figure(figsize=(6,4)) ax = fig.add_axes([0.05,0.08,0.9,0.9]) # Add the arctic data to the plot @@ -132,55 +140,54 @@ def plot_timeseries(log, field, dtg, arctic, antarctic, expon, dtg_base=None, ar ax.xaxis.set_minor_locator(mdates.MonthLocator()) # Add a text box that prints the test case name and the baseline case name (if given) - try: - text_field = "Test/Case: {}\nBaseline: {}".format(casename,base_casename) - from matplotlib.offsetbox import AnchoredText - anchored_text = AnchoredText(text_field,loc=2) - ax.add_artist(anchored_text) - except: - text_field = "Test/Case: {}".format(casename) - from matplotlib.offsetbox import AnchoredText - anchored_text = AnchoredText(text_field,loc=2) - ax.add_artist(anchored_text) + if base_casename is None: + text_field = "{}".format(casename) + else: + text_field = "{}\n{}".format(casename,base_casename) + + from matplotlib.offsetbox import AnchoredText + anchored_text = AnchoredText(text_field,loc='upper left') + anchored_text.patch.set_alpha(0.5) + ax.add_artist(anchored_text) - ax.legend(loc='upper right') + ax.legend(loc='upper right',framealpha=0.5) # Add grid lines if the `--grid` argument was passed at the command line. if grid: ax.grid(ls='--') # Reduce the number of ticks on the y axis - nbins = 10 - try: - minval = min( \ - min(min(arctic), min(antarctic)), \ - min(min(arctic_base), min(antarctic_base))) - maxval = max( \ - max(max(arctic), max(antarctic)), \ - max(max(arctic_base), max(antarctic_base))) - except: - minval = min(min(arctic), min(antarctic)) - maxval = max(max(arctic), max(antarctic)) - step = (maxval-minval)/nbins - ax.yaxis.set_ticks(np.arange(minval, maxval+step, step)) +# nbins = 10 +# try: +# minval = min( \ +# min(min(arctic), min(antarctic)), \ +# min(min(arctic_base), min(antarctic_base))) +# maxval = max( \ +# max(max(arctic), max(antarctic)), \ +# max(max(arctic_base), max(antarctic_base))) +# except: +# minval = min(min(arctic), min(antarctic)) +# maxval = max(max(arctic), max(antarctic)) +# step = (maxval-minval)/nbins +# ax.yaxis.set_ticks(np.arange(minval, maxval+step, step)) # Format the y-axis tick labels, based on whether or not the values in the log file # are in scientific notation or float notation. if expon: - ax.yaxis.set_major_formatter(ticker.FormatStrFormatter('%0.3e')) + ax.yaxis.set_major_formatter(ticker.FormatStrFormatter('%0.1e')) else: - ax.yaxis.set_major_formatter(ticker.FormatStrFormatter('%0.5f')) + ax.yaxis.set_major_formatter(ticker.FormatStrFormatter('%0.3f')) # Rotate and right align the x labels for tick in ax.get_xticklabels(): - tick.set_rotation(45) + tick.set_rotation(30) # Create an output file and save the figure field_tmp = field.split('(')[0].rstrip() try: - outfile = '{}_{}_base-{}.png'.format(field_tmp.replace(' ','_'), casename,base_casename) + outfile = '{}_{}_base-{}.png'.format(field_tmp.replace(' ','_'),casename.replace(' ','_'),base_casename.replace(' ','_')) except: - outfile = '{}_{}.png'.format(field_tmp.replace(' ','_'), casename) + outfile = '{}_{}.png'.format(field_tmp.replace(' ','_'), casename.replace(' ','_')) logger.info('Saving file to {}'.format(outfile)) plt.savefig(outfile,dpi=300,bbox_inches='tight') @@ -204,6 +211,10 @@ def main(): dataset, if desired. A specific log file or case directory can \ be passed. If a directory is passed, the most recent log file \ will be used.') + parser.add_argument('--case', dest='casename', help='User specified casename for plots.', \ + action='store') + parser.add_argument('--basecase', dest='base_casename', help='User specified base casename \ + for plots.', action='store') parser.add_argument('-v', '--verbose', dest='verbose', help='Print debug output?', \ action='store_true') parser.add_argument('--area', dest='area', help='Create a plot for total ice area?', \ @@ -227,6 +238,8 @@ def main(): parser.set_defaults(snow_volume=False) parser.set_defaults(speed=False) parser.set_defaults(grid=False) + parser.set_defaults(casename=None) + parser.set_defaults(base_casename=None) args = parser.parse_args() @@ -268,7 +281,7 @@ def main(): logger.debug('{} is a file'.format(args.log_dir)) log = args.log_dir log_dir = args.log_dir.rsplit('/',1)[0] - logger.info('Log file = {}'.format(log)) + if args.base_dir: if os.path.isdir(args.base_dir): base_log = find_logfile(args.base_dir) @@ -278,6 +291,9 @@ def main(): base_dir = args.base_dir.rsplit('/',1)[0] logger.info('Base Log file = {}'.format(base_log)) + logger.info('casename = {}'.format(args.casename)) + logger.info('Log file = {}'.format(log)) + # Loop through each field and create the plot for field in fieldlist: logger.debug('Current field = {}'.format(field)) @@ -290,9 +306,11 @@ def main(): # Plot the data if args.base_dir: plot_timeseries(log_dir, field, dtg, arctic, antarctic, expon, dtg_base, \ - arctic_base, antarctic_base, base_dir, grid=args.grid) + arctic_base, antarctic_base, base_dir, grid=args.grid, \ + casename=args.casename, base_casename=args.base_casename) else: - plot_timeseries(log_dir, field, dtg, arctic, antarctic, expon, grid=args.grid) + plot_timeseries(log_dir, field, dtg, arctic, antarctic, expon, grid=args.grid, \ + casename=args.casename) if __name__ == "__main__": main() diff --git a/doc/source/developer_guide/dg_scripts.rst b/doc/source/developer_guide/dg_scripts.rst index dac5e9a52..d4b29acbb 100644 --- a/doc/source/developer_guide/dg_scripts.rst +++ b/doc/source/developer_guide/dg_scripts.rst @@ -22,6 +22,8 @@ The directory structure under configure/scripts is as follows. | **cice.run.setup.csh** sets up the run scripts | **cice.settings** defines environment, model configuration and run settings | **cice.test.setup.csh** creates configurations for testing the model +| **ciceplots.csh** general script to generate timeseries and 2d CICE plots +| **ciceplots2d.py** python script to generate 2d CICE plots | **ice_in** namelist input data | **machines/** machine specific files to set env and Macros | **makdep.c** determines module dependencies @@ -31,8 +33,7 @@ The directory structure under configure/scripts is as follows. | **parse_settings.sh** replaces settings with command-line configuration | **setup_run_dirs.csh** creates the case run directories | **set_version_number.csh** updates the model version number from the **cice.setup** command line -| **timeseries.csh** generates PNG timeseries plots from output files, using GNUPLOT -| **timeseries.py** generates PNG timeseries plots from output files, using Python +| **timeseries.py** python script to generate timeseries plots from CICE log file | **tests/** scripts for configuring and running basic tests .. _dev_strategy: diff --git a/doc/source/user_guide/ug_case_settings.rst b/doc/source/user_guide/ug_case_settings.rst index 8e7b154db..a2740932c 100644 --- a/doc/source/user_guide/ug_case_settings.rst +++ b/doc/source/user_guide/ug_case_settings.rst @@ -673,6 +673,8 @@ forcing_nml "``calc_strair``", "``.false.``", "read wind stress and speed from files", "``.true.``" "", "``.true.``", "calculate wind stress and speed", "" "``calc_Tsfc``", "logical", "calculate surface temperature", "``.true.``" + "``congel_freeze``", "``one-step``", "immediately freeze congelation ice", "``two-step``" + "", "``two-step``", "delayed freezing of congelation ice", "" "``cpl_frazil``", "``external``", "frazil water/salt fluxes are handled outside of Icepack", "``fresh_ice_correction``" "", "``fresh_ice_correction``", "correct fresh-ice frazil water/salt fluxes for mushy physics", "" "", "``internal``", "send full frazil water/salt fluxes for mushy physics", "" diff --git a/doc/source/user_guide/ug_running.rst b/doc/source/user_guide/ug_running.rst index 7ac37f16e..021c5bcbe 100644 --- a/doc/source/user_guide/ug_running.rst +++ b/doc/source/user_guide/ug_running.rst @@ -845,12 +845,13 @@ A few notes about the conda configuration: mpirun -np ${ntasks} --oversubscribe ./cice >&! \$ICE_RUNLOG_FILE - It is not recommeded to run other test suites than ``quick_suite`` or ``travis_suite`` on a personal computer. -- The conda environment is automatically activated when compiling or running the model using the ``./cice.build`` and ``./cice.run`` scripts in the case directory. These scripts source the file ``env.conda_{linux.macos}``, which calls ``conda activate cice``. +- If needed, the conda environment is automatically activated when compiling or running the model using the ``./cice.build`` and ``./cice.run`` scripts in the case directory. These scripts source the file ``env.conda_{linux.macos}``, which calls ``conda activate cice``. - To use the "cice" conda environment with the Python plotting (see :ref:`timeseries`) and quality control (QC) scripts (see :ref:`CodeValidation`), you must manually activate the environment: .. code-block:: bash cd ~/cice-dirs/cases/case1 + conda env create -f configuration/scripts/machines/environment.yml --force conda activate cice python timeseries.py ~/cice-dirs/cases/case1/logs conda deactivate # to deactivate the environment @@ -955,58 +956,49 @@ in shell startup files or otherwise at users discretion: .. _timeseries: -Timeseries Plotting +Plotting Tools ------------------- -The CICE scripts include two scripts that will generate timeseries figures from a -diagnostic output file, a Python version (``timeseries.py``) and a csh version -(``timeseries.csh``). Both scripts create the same set of plots, but the Python -script has more capabilities, and it's likely that the csh -script will be removed in the future. +CICE includes a couple of simple scripts to generate plots. The ``timeseries.py`` +scripts generates northern and southern hemisphere timeseries plots for several +fields from the CICE log file. The ``ciceplots2d.py`` script generates some +two-dimensional plots from CICE history files as global and polar projections. +The script ``ciceplots.csh`` is a general script that sets up the inputs for the +python plotting tools and calls them. Both python tools produce png files. -To use the ``timeseries.py`` script, the following requirements must be met: +To use the python scripts, the following python packages are required: -* Python v2.7 or later -* numpy Python package -* matplotlib Python package -* datetime Python package +* Python3 +* numpy +* matplotlib +* re +* datetime +* netcdf4 +* basemap, basemap-data, basemap-data-hires -See :ref:`CodeValidation` for additional information about how to setup the Python -environment, but we recommend using ``pip`` as follows: :: +The easist way to install the package is via the cice env file provided with CICE via conda: - pip install --user numpy - pip install --user matplotlib - pip install --user datetime - -When creating a case or test via ``cice.setup``, the ``timeseries.csh`` and -``timeseries.py`` scripts are automatically copied to the case directory. -Alternatively, the plotting scripts can be found in ``./configuration/scripts``, and can be -run from any directory. - -The Python script can be passed a directory, a specific log file, or no directory at all: + .. code-block:: bash - - If a directory is passed, the script will look either in that directory or in - directory/logs for a filename like cice.run*. As such, users can point the script - to either a case directory or the ``logs`` directory directly. The script will use - the file with the most recent creation time. - - If a specific file is passed the script parses that file, assuming that the file - matches the same form of cice.run* files. - - If nothing is passed, the script will look for log files or a ``logs`` directory in the - directory from where the script was run. + conda env create -f configuration/scripts/machines/environment.yml --force + conda activate cice -For example: +Then edit the ``ciceplots.csh`` script and run it. ``ciceplots.csh`` also demonstrates +how to call each python script separately. -Run the timeseries script on the desired case. :: +When creating a case or test via ``cice.setup``, these three plotting scripts +are automatically copied to the case directory. +Alternatively, the plotting scripts can be found in ``./configuration/scripts`` and can +be run as needed. -$ python timeseries.py /p/work1/turner/CICE_RUNS/conrad_intel_smoke_col_1x1_diag1_run1year.t00/ +Briefly, the ``timeseries.py`` script has a few options but can be called as follows: -or :: + .. code-block:: bash -$ python timeseries.py /p/work1/turner/CICE_RUNS/conrad_intel_smoke_col_1x1_diag1_run1year.t00/logs - -The output figures are placed in the directory where the ``timeseries.py`` script is run. + ./timeseries.py /p/work1/turner/CICE_RUNS/conrad_intel_smoke_col_1x1_diag1_run1year.t00 --grid --case CICE6.0.1 -The plotting script will plot the following variables by default, but you can also select +The timeseries script parses the log file, so the temporal resolution is based on the log output frequency. +The timeseries plotting script will plot the following variables by default, but you can also select specific plots to create via the optional command line arguments. - total ice area (:math:`km^2`) @@ -1015,30 +1007,14 @@ specific plots to create via the optional command line arguments. - total snow volume (:math:`m^3`) - RMS ice speed (:math:`m/s`) -For example, to plot only total ice volume and total snow volume :: +The ``ciceplots2d.py`` script is called as follows: -$ python timeseries.py /p/work1/turner/CICE_RUNS/conrad_intel_smoke_col_1x1_diag1_run1year.t00/ --volume --snw_vol - -To generate plots for all of the cases within a suite with a testid, create and run a script such as :: - - #!/bin/csh - foreach dir (`ls -1 | grep testid`) - echo $dir - python timeseries.py $dir - end - -Plots are only made for a single output file at a time. The ability to plot output from -a series of cice.run* files is not currently possible, but may be added in the future. -However, using the ``--bdir`` option will plot two datasets (from log files) on the -same figure. - -For the latest help information for the script, run :: - -$ python timeseries.py -h - -The ``timeseries.csh`` script works basically the same way as the Python version, however it -does not include all of the capabilities present in the Python version. + .. code-block:: bash -To use the C-Shell version of the script, :: + ./ciceplots2d.py aice /p/work1/turner/CICE_RUNS/conrad_intel_smoke_col_1x1_diag1_run1year.t00/history/iceh.2005-09.nc CICE6.0.1 "Sept 2005 Mean" 2005Sep -$ ./timeseries.csh /p/work1/turner/CICE_RUNS/conrad_intel_smoke_col_1x1_diag1_run1year.t00/ +In the example above, a global, northern hemisphere, and southern hemisphere plot would be created +for the aice field from iceh.2005-09.nc file. Titles on the plot would reference CICE6.0.1 and +"Sept 2005 Mean" and the png files would contain the string 2005Sep as well as the field name and region. +The two-dimensional plots are generated using the scatter feature from matplotlib, so they are fairly +primitive. diff --git a/icepack b/icepack index ae69b8069..4c8709525 160000 --- a/icepack +++ b/icepack @@ -1 +1 @@ -Subproject commit ae69b806990ef2412e2f714c5b4ba4c096b163b6 +Subproject commit 4c87095256c1c599c3ccaa857a95744158751a60