diff --git a/src/core_atmosphere/Registry.xml b/src/core_atmosphere/Registry.xml index 253970d1b0..ed047a19fe 100644 --- a/src/core_atmosphere/Registry.xml +++ b/src/core_atmosphere/Registry.xml @@ -355,7 +355,7 @@ - + @@ -1029,16 +1029,18 @@ - - - - - + + + + + + \brief Checks for consistency of sfc update namelist/stream list settings + !> \author Dom Heinzeller + !> \date 01 December 2016 + !> \details + !> This routine checks for consistency between the surface update settings + !> in the namelist (config_sst_update) and the stream list settings. If + !> config_sst_update is true, the surface update stream 'surface' must be + !> present in streams.atmosphere. As an immutable stream, the 'surface' + !> stream is automatically added to the list of streams, even if it is not + !> included in streams.atmosphere; however, its input/output intervals are + !> set to 'none'. Thus, if config_sst_update is true and input_interval is + !> 'none' the code will abort. + !> Similarily, if config_sst_update is false, the 'surface' stream is set + !> to inactive to avoid reading the stream. This is necessary because + !> reading the stream without performing the necessary adjustments triggered + !> by config_sst_update can cause the model to crash/segfault. + ! + !----------------------------------------------------------------------- + subroutine atm_sanity_check_sfc_update(domain) + + use mpas_derived_types, only : MPAS_STREAM_MGR_NOERR, & + MPAS_STREAM_PROPERTY_ACTIVE + use mpas_stream_manager, only : MPAS_stream_mgr_get_property, & + MPAS_stream_mgr_set_property, & + MPAS_stream_mgr_begin_iteration, & + MPAS_stream_mgr_get_next_stream + use mpas_pool_routines, only : mpas_pool_get_config + + implicit none + + type (domain_type), intent(inout) :: domain + + logical, pointer :: config_sst_update + character (len=StrKIND) :: stream_id + character (len=StrKIND) :: input_interval + logical :: is_active + logical :: found_stream + integer :: ierr + + call mpas_pool_get_config(domain%blocklist%configs, 'config_sst_update', config_sst_update) + found_stream =.false. + + call MPAS_stream_mgr_begin_iteration(domain % streamManager) + do while (MPAS_stream_mgr_get_next_stream(domain % streamManager, streamID=stream_id, inputIntervalProperty=input_interval)) + call MPAS_stream_mgr_get_property(domain % streamManager, stream_id, MPAS_STREAM_PROPERTY_ACTIVE, is_active, ierr=ierr) + if (stream_id == 'surface' .and. (.not. config_sst_update)) then + call MPAS_stream_mgr_get_property(domain % streamManager, stream_id, MPAS_STREAM_PROPERTY_ACTIVE, is_active, ierr=ierr) + if (.not. ierr == MPAS_STREAM_MGR_NOERR) then + call mpas_dmpar_global_abort("ERROR while checking if surface update stream 'surface' is active") + end if + if (is_active) then + write(0,*) " ** Setting surface update stream 'surface' to inactive since sst updates are disabled" + call MPAS_stream_mgr_set_property(domain % streamManager, stream_id, MPAS_STREAM_PROPERTY_ACTIVE, .false., ierr=ierr) + if (.not. ierr == MPAS_STREAM_MGR_NOERR) then + call mpas_dmpar_global_abort("ERROR while deactivating surface update stream 'surface'") + end if + end if + found_stream = .true. + else if (stream_id == 'surface' .and. trim(input_interval) /= 'none') then + found_stream = .true. + end if + end do + + if ((.not. found_stream) .and. config_sst_update) then + call mpas_dmpar_global_abort("ERROR: sst updates requested, but surface update stream 'surface' not found") + end if + + end subroutine atm_sanity_check_sfc_update + + function atm_core_run(domain) result(ierr) use mpas_timekeeping diff --git a/src/core_atmosphere/physics/mpas_atmphys_manager.F b/src/core_atmosphere/physics/mpas_atmphys_manager.F index f553da6a56..06b01cbf42 100644 --- a/src/core_atmosphere/physics/mpas_atmphys_manager.F +++ b/src/core_atmosphere/physics/mpas_atmphys_manager.F @@ -211,8 +211,10 @@ subroutine physics_timetracker(domain,dt,clock,itimestep,xtime_s) !sea-ice coverage: if(mpas_is_alarm_ringing(clock,sfcbdyAlarmID,ierr=ierr)) then call mpas_reset_clock_alarm(clock,sfcbdyAlarmID,ierr=ierr) - if(config_sst_update) & + if (config_sst_update) then + write(0,*) '--- time to update surface information from surface update file.' call physics_update_sst(domain%dminfo,config_frac_seaice,mesh,sfc_input,diag_physics) + end if endif !apply a diurnal cycle to the sea-surface temperature: diff --git a/src/driver/mpas_subdriver.F b/src/driver/mpas_subdriver.F index 1a3528f9f6..c9b1918692 100644 --- a/src/driver/mpas_subdriver.F +++ b/src/driver/mpas_subdriver.F @@ -49,7 +49,10 @@ subroutine mpas_init() use mpas_c_interfacing, only : mpas_f_to_c_string, mpas_c_to_f_string use mpas_timekeeping, only : mpas_get_clock_time, mpas_get_time use mpas_bootstrapping, only : mpas_bootstrap_framework_phase1, mpas_bootstrap_framework_phase2 - +#ifdef CORE_ATMOSPHERE + use atm_core, only: atm_sanity_check_sfc_update +#endif + implicit none integer :: iArg, nArgs @@ -298,6 +301,10 @@ end subroutine xml_stream_get_attributes if (c_ierr /= 0) then call mpas_dmpar_abort(domain_ptr % dminfo) end if +#ifdef CORE_ATMOSPHERE + write(0,*) " ** Performing sanity check of surface update stream properties for atmosphere core" + call atm_sanity_check_sfc_update(domain_ptr) +#endif ! ! Finalize the setup of blocks and fields diff --git a/src/framework/mpas_stream_list_types.inc b/src/framework/mpas_stream_list_types.inc index 9bb4aec851..2fa5d3dbd1 100644 --- a/src/framework/mpas_stream_list_types.inc +++ b/src/framework/mpas_stream_list_types.inc @@ -40,5 +40,8 @@ type (MPAS_stream_list_type), pointer :: xref => null() type (MPAS_stream_list_type), pointer :: next => null() + character(len=StrKIND) :: interval_in + character(len=StrKIND) :: interval_out + end type MPAS_stream_list_type diff --git a/src/framework/mpas_stream_manager.F b/src/framework/mpas_stream_manager.F index 7ea5ef287d..3a1f12eaa6 100644 --- a/src/framework/mpas_stream_manager.F +++ b/src/framework/mpas_stream_manager.F @@ -272,6 +272,10 @@ end subroutine MPAS_stream_mgr_finalize!}}} !> specified using the optional "recordInterval" argument; if this argument !> is not supplied, the stream manager will assume that this interval is !> equal to the shortest period of any periodic alarm attached to the stream. + !> The optional arguments inputInterval and outputInterval specify the the + !> interval at which files are read/written and are set to 'none' if not + !> specified. This is necessary for immutable streams defined in the + !> registry but not present in the stream list file of the core to run. !> The optional argument 'realPrecision' specifies the precision of !> real-valued fields in the files associated with the stream; this !> argument may take on values MPAS_IO_SINGLE_PRECISION, @@ -291,7 +295,8 @@ end subroutine MPAS_stream_mgr_finalize!}}} ! !----------------------------------------------------------------------- subroutine MPAS_stream_mgr_create_stream(manager, streamID, direction, filename, & - filenameInterval, referenceTime, recordInterval, & + filenameInterval, inputInterval, outputInterval, & + referenceTime, recordInterval, & realPrecision, clobberMode, ioType, ierr) !{{{ use mpas_io, only : MPAS_IO_PNETCDF @@ -305,6 +310,8 @@ subroutine MPAS_stream_mgr_create_stream(manager, streamID, direction, filename, integer, intent(in) :: direction character (len=*), intent(in) :: filename character (len=*), intent(in), optional :: filenameInterval + character (len=*), intent(in), optional :: inputInterval + character (len=*), intent(in), optional :: outputInterval type (MPAS_Time_type), intent(in), optional :: referenceTime type (MPAS_TimeInterval_type), intent(in), optional :: recordInterval integer, intent(in), optional :: realPrecision @@ -350,6 +357,20 @@ subroutine MPAS_stream_mgr_create_stream(manager, streamID, direction, filename, new_stream % filename_interval = 'none' end if + ! Input interval is 'none' by deault, but is set through the set_property routine. + if (present(inputInterval)) then + new_stream % interval_in = inputInterval + else + new_stream % interval_in = 'none' + end if + + ! Output interval is 'none' by deault, but is set through the set_property routine. + if (present(outputInterval)) then + new_stream % interval_out = outputInterval + else + new_stream % interval_out = 'none' + end if + new_stream % nRecords = 0 if (present(clobberMode)) then new_stream % clobber_mode = clobberMode @@ -1632,6 +1653,12 @@ subroutine MPAS_stream_mgr_set_property_char(manager, streamID, propertyName, pr case (MPAS_STREAM_PROPERTY_FILENAME_INTV) stream_cursor % filename_interval = propertyValue + case (MPAS_STREAM_PROPERTY_INTERVAL_IN) + stream_cursor % interval_in = propertyValue + + case (MPAS_STREAM_PROPERTY_INTERVAL_OUT) + stream_cursor % interval_out = propertyValue + case (MPAS_STREAM_PROPERTY_REF_TIME) call mpas_set_time(stream_cursor % referenceTime, dateTimeString=propertyValue) @@ -2140,7 +2167,7 @@ subroutine MPAS_stream_mgr_add_att_int(manager, attName, attVal, streamID, ierr) if (present(streamID)) then addedAttribute = .false. nullify(stream_cursor) - do while (MPAS_stream_list_query(manager % streams, streamID, stream_cursor, ierr=err_local)) + do while (.not. MPAS_stream_list_query(manager % streams, streamID, stream_cursor, ierr=err_local)) addedAttribute = .true. att_pool => stream_cursor % att_pool err_level = mpas_pool_get_error_level() @@ -2858,7 +2885,7 @@ subroutine write_stream(manager, stream, blockID, timeLevel, mgLevel, forceWrite integer, intent(out) :: ierr type (MPAS_stream_list_type), pointer :: alarm_cursor - type (MPAS_Time_type) :: ref_time + type (MPAS_Time_type) :: now_time, ref_time type (MPAS_TimeInterval_type) :: temp_interval type (MPAS_TimeInterval_type) :: filename_interval character (len=StrKIND) :: now_string, time_string @@ -2868,6 +2895,8 @@ subroutine write_stream(manager, stream, blockID, timeLevel, mgLevel, forceWrite logical :: clobberRecords, clobberFiles, truncateFiles integer :: maxRecords, tempRecord integer :: local_ierr, threadNum + logical :: final_input_only + logical :: final_output_only threadNum = mpas_threading_get_thread_num() @@ -2899,6 +2928,16 @@ subroutine write_stream(manager, stream, blockID, timeLevel, mgLevel, forceWrite alarm_cursor => stream % alarmList_out % head do while (associated(alarm_cursor)) if (mpas_is_alarm_ringing(manager % streamClock, alarm_cursor % name, ierr=local_ierr)) then + if (trim(stream % interval_in) == 'final_only') then + final_input_only = .true. + else + final_input_only = .false. + end if + if (trim(stream % interval_out) == 'final_only') then + final_output_only = .true. + else + final_output_only = .false. + end if ringing_alarm = .true. exit end if @@ -2940,6 +2979,10 @@ subroutine write_stream(manager, stream, blockID, timeLevel, mgLevel, forceWrite if ( stream % filename_interval /= 'none' ) then call mpas_set_timeInterval(filename_interval, timeString=stream % filename_interval) call mpas_build_stream_filename(stream % referenceTime, writeTime, filename_interval, stream % filename_template, blockID, stream % filename, ierr=local_ierr) + else if (final_input_only .or. final_output_only) then + now_time = mpas_get_clock_time(manager % streamClock, MPAS_NOW, ierr=local_ierr) + call mpas_get_time(now_time, dateTimeString=time_string) + call mpas_expand_string(time_string, blockID, stream % filename_template, stream % filename) else call mpas_get_time(stream % referenceTime, dateTimeString=time_string) call mpas_expand_string(time_string, blockID, stream % filename_template, stream % filename) @@ -3013,6 +3056,10 @@ subroutine write_stream(manager, stream, blockID, timeLevel, mgLevel, forceWrite call mpas_set_timeInterval(filename_interval, timeString=stream % filename_interval) call mpas_build_stream_filename(stream % referenceTime, writeTime, filename_interval, stream % filename_template, blockID, temp_filename, ierr=local_ierr) + else if (final_input_only .or. final_output_only) then + now_time = mpas_get_clock_time(manager % streamClock, MPAS_NOW, ierr=local_ierr) + call mpas_get_time(now_time, dateTimeString=time_string) + call mpas_expand_string(time_string, blockID, stream % filename_template, temp_filename) else call mpas_get_time(stream % referenceTime, dateTimeString=time_string) call mpas_expand_string(time_string, blockID, stream % filename_template, temp_filename) @@ -3906,13 +3953,13 @@ subroutine mpas_build_stream_filename(ref_time, when, filename_interval, filenam direction = -1 end if -! call mpas_get_time(when, dateTimeString=temp_string) + call mpas_get_time(when, dateTimeString=temp_string) STREAM_DEBUG_WRITE(' ** when is: ' COMMA trim(temp_string)) -! call mpas_get_time(ref_time, dateTimeString=temp_string) + call mpas_get_time(ref_time, dateTimeString=temp_string) STREAM_DEBUG_WRITE(' ** ref_time is: ' COMMA trim(temp_string)) -! call mpas_get_timeInterval(intv, timeString=temp_string) + call mpas_get_timeInterval(intv, timeString=temp_string) STREAM_DEBUG_WRITE(' ** intv is: ' COMMA trim(temp_string)) call mpas_interval_division(ref_time, intv, filename_interval, nrecs, rem) @@ -5341,6 +5388,7 @@ end subroutine MPAS_stream_mgr_begin_iteration !}}} !----------------------------------------------------------------------- logical function MPAS_stream_mgr_get_next_stream(manager, streamID, directionProperty, activeProperty, & !{{{ immutableProperty, filenameTemplateProperty, & + inputIntervalProperty, outputIntervalProperty, & referenceTimeProperty, recordIntervalProperty, precisionProperty, & filenameIntervalProperty, clobberProperty) result(validStream) @@ -5352,6 +5400,8 @@ logical function MPAS_stream_mgr_get_next_stream(manager, streamID, directionPro logical, intent(out), optional :: activeProperty !< Output: Logical describing if the stream is active or not logical, intent(out), optional :: immutableProperty !< Output: Logical describing if the stream is immutable or not character (len=StrKIND), intent(out), optional :: filenameTemplateProperty !< Output: String containing the filename template for the stream + character (len=StrKIND), intent(out), optional :: inputIntervalProperty !< Output: String containing the input interval for the stream + character (len=StrKIND), intent(out), optional :: outputIntervalProperty !< Output: String containing the output interval for the stream character (len=StrKIND), intent(out), optional :: referenceTimeProperty !< Output: String containing the reference time for the stream character (len=StrKIND), intent(out), optional :: recordIntervalProperty !< Output: String containing the record interval for the stream integer, intent(out), optional :: precisionProperty !< Output: Integer describing the precision of the stream @@ -5404,6 +5454,14 @@ logical function MPAS_stream_mgr_get_next_stream(manager, streamID, directionPro filenameTemplateProperty = manager % currentStream % filename_template end if + if ( present(inputIntervalProperty) ) then + inputIntervalProperty = manager % currentStream % interval_in + end if + + if ( present(outputIntervalProperty) ) then + outputIntervalProperty = manager % currentStream % interval_out + end if + if ( present(referenceTimeProperty) ) then call mpas_get_time(manager % currentStream % referenceTime, dateTimeString=referenceTimeProperty) end if @@ -5545,19 +5603,22 @@ end module mpas_stream_manager !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -subroutine stream_mgr_create_stream_c(manager_c, streamID_c, direction_c, filename_c, filename_intv_c, ref_time_c, rec_intv_c, & - immutable_c, precision_c, clobber_c, iotype_c, ierr_c) bind(c) !{{{ +subroutine stream_mgr_create_stream_c(manager_c, streamID_c, direction_c, filename_c, filename_intv_c, interval_in_c, interval_out_c, & + ref_time_c, rec_intv_c, immutable_c, precision_c, clobber_c, iotype_c, ierr_c) bind(c) !{{{ use mpas_c_interfacing, only : mpas_c_to_f_string use iso_c_binding, only : c_char, c_int, c_ptr, c_f_pointer - use mpas_derived_types, only : MPAS_streamManager_type, & + use mpas_derived_types, only : MPAS_streamManager_type, MPAS_TimeInterval_type, & MPAS_STREAM_MGR_NOERR, MPAS_STREAM_PROPERTY_FILENAME, & MPAS_STREAM_PROPERTY_FILENAME_INTV, MPAS_STREAM_PROPERTY_REF_TIME, & MPAS_STREAM_PROPERTY_RECORD_INTV, MPAS_STREAM_PROPERTY_PRECISION, & MPAS_STREAM_PROPERTY_CLOBBER, MPAS_STREAM_CLOBBER_NEVER, MPAS_STREAM_CLOBBER_APPEND, & - MPAS_STREAM_CLOBBER_TRUNCATE, MPAS_STREAM_CLOBBER_OVERWRITE, MPAS_STREAM_PROPERTY_IOTYPE + MPAS_STREAM_CLOBBER_TRUNCATE, MPAS_STREAM_CLOBBER_OVERWRITE, MPAS_STREAM_PROPERTY_IOTYPE, & + MPAS_STREAM_PROPERTY_INTERVAL_IN, MPAS_STREAM_PROPERTY_INTERVAL_OUT, & + MPAS_STREAM_PROPERTY_ACTIVE use mpas_stream_manager, only : MPAS_stream_mgr_create_stream, MPAS_stream_mgr_set_property use mpas_kind_types, only : StrKIND + use mpas_timekeeping use mpas_io, only : MPAS_IO_SINGLE_PRECISION, MPAS_IO_DOUBLE_PRECISION, MPAS_IO_NATIVE_PRECISION, & MPAS_IO_NETCDF, MPAS_IO_PNETCDF, MPAS_IO_NETCDF4, MPAS_IO_PNETCDF5 use mpas_io_units, only : stderrUnit @@ -5569,6 +5630,8 @@ subroutine stream_mgr_create_stream_c(manager_c, streamID_c, direction_c, filena integer(kind=c_int) :: direction_c character(kind=c_char) :: filename_c(*) character(kind=c_char) :: filename_intv_c(*) + character(kind=c_char) :: interval_in_c(*) + character(kind=c_char) :: interval_out_c(*) character(kind=c_char) :: ref_time_c(*) character(kind=c_char) :: rec_intv_c(*) integer(kind=c_int) :: immutable_c @@ -5578,7 +5641,7 @@ subroutine stream_mgr_create_stream_c(manager_c, streamID_c, direction_c, filena integer(kind=c_int) :: ierr_c type (MPAS_streamManager_type), pointer :: manager - character(len=StrKIND) :: streamID, filename, filename_interval, reference_time, record_interval + character(len=StrKIND) :: streamID, filename, filename_interval, interval_in, interval_out, reference_time, record_interval integer :: direction, immutable, prec, ierr integer :: clobber_mode, iotype @@ -5587,6 +5650,8 @@ subroutine stream_mgr_create_stream_c(manager_c, streamID_c, direction_c, filena direction = direction_c call mpas_c_to_f_string(filename_c, filename) call mpas_c_to_f_string(filename_intv_c, filename_interval) + call mpas_c_to_f_string(interval_in_c, interval_in) + call mpas_c_to_f_string(interval_out_c, interval_out) call mpas_c_to_f_string(ref_time_c, reference_time) call mpas_c_to_f_string(rec_intv_c, record_interval) immutable = immutable_c @@ -5652,6 +5717,9 @@ subroutine stream_mgr_create_stream_c(manager_c, streamID_c, direction_c, filena clobberMode=clobber_mode, ioType=iotype, ierr=ierr) end if + call MPAS_stream_mgr_set_property(manager, streamID, MPAS_STREAM_PROPERTY_INTERVAL_IN, interval_in, ierr=ierr) + call MPAS_stream_mgr_set_property(manager, streamID, MPAS_STREAM_PROPERTY_INTERVAL_OUT, interval_out, ierr=ierr) + if (reference_time /= 'initial_time') then call MPAS_stream_mgr_set_property(manager, streamID, MPAS_STREAM_PROPERTY_REF_TIME, reference_time, ierr=ierr) end if @@ -5664,6 +5732,10 @@ subroutine stream_mgr_create_stream_c(manager_c, streamID_c, direction_c, filena call MPAS_stream_mgr_set_property(manager, streamID, MPAS_STREAM_PROPERTY_FILENAME_INTV, filename_interval, ierr=ierr) end if + if (direction_c == 4) then + call MPAS_stream_mgr_set_property(manager, streamID, MPAS_STREAM_PROPERTY_ACTIVE, .false., ierr=ierr) + end if + if (ierr == MPAS_STREAM_MGR_NOERR) then ierr_c = 0 else @@ -5813,7 +5885,8 @@ subroutine stream_mgr_add_alarm_c(manager_c, streamID_c, direction_c, alarmTime_ use mpas_c_interfacing, only : mpas_c_to_f_string use iso_c_binding, only : c_char, c_int, c_ptr, c_f_pointer use mpas_derived_types, only : MPAS_streamManager_type, MPAS_Clock_type, MPAS_Time_type, MPAS_TimeInterval_type, & - MPAS_STREAM_MGR_NOERR, MPAS_STREAM_INPUT, MPAS_STREAM_OUTPUT, MPAS_START_TIME + MPAS_STREAM_MGR_NOERR, MPAS_STREAM_INPUT, MPAS_STREAM_OUTPUT, MPAS_START_TIME, & + MPAS_STOP_TIME use mpas_stream_manager, only : MPAS_stream_mgr_get_clock, MPAS_stream_mgr_add_alarm use mpas_kind_types, only : StrKIND use mpas_timekeeping, only : mpas_add_clock_alarm, mpas_set_time, mpas_set_timeInterval, mpas_get_clock_time @@ -5858,13 +5931,15 @@ subroutine stream_mgr_add_alarm_c(manager_c, streamID_c, direction_c, alarmTime_ call MPAS_stream_mgr_get_clock(manager, clock) - if (trim(alarmTime) == 'start') then + if (trim(alarmTime) == 'start' .and. trim(alarmInterval) == 'final_only') then + alarmTime_local = mpas_get_clock_time(clock, MPAS_STOP_TIME, ierr=ierr) + else if (trim(alarmTime) == 'start') then alarmTime_local = mpas_get_clock_time(clock, MPAS_START_TIME, ierr=ierr) else call mpas_set_time(alarmTime_local, dateTimeString=alarmTime) end if - if (trim(alarmInterval) == 'initial_only') then + if (trim(alarmInterval) == 'initial_only' .or. trim(alarmInterval) == 'final_only') then call mpas_add_clock_alarm(clock, alarmID, alarmTime_local, ierr=ierr) else call mpas_set_timeInterval(alarmInterval_local, timeString=alarmInterval) diff --git a/src/framework/mpas_stream_manager_types.inc b/src/framework/mpas_stream_manager_types.inc index dd53601e34..550ac0d27b 100644 --- a/src/framework/mpas_stream_manager_types.inc +++ b/src/framework/mpas_stream_manager_types.inc @@ -20,7 +20,9 @@ MPAS_STREAM_PROPERTY_PRECISION = 10, & MPAS_STREAM_PROPERTY_FILENAME_INTV = 11, & MPAS_STREAM_PROPERTY_CLOBBER = 12, & - MPAS_STREAM_PROPERTY_IOTYPE = 13 + MPAS_STREAM_PROPERTY_IOTYPE = 13, & + MPAS_STREAM_PROPERTY_INTERVAL_IN = 14, & + MPAS_STREAM_PROPERTY_INTERVAL_OUT = 15 integer, public, parameter :: MPAS_STREAM_CLOBBER_NEVER = 100, & MPAS_STREAM_CLOBBER_APPEND = 101, & diff --git a/src/framework/mpas_timekeeping_types.inc b/src/framework/mpas_timekeeping_types.inc index 430c471d2a..bcabf595fc 100644 --- a/src/framework/mpas_timekeeping_types.inc +++ b/src/framework/mpas_timekeeping_types.inc @@ -26,13 +26,13 @@ type (MPAS_Time_type) :: ringTime type (MPAS_Time_type) :: prevRingTime type (MPAS_TimeInterval_type) :: ringTimeInterval - type (MPAS_Alarm_type), pointer :: next + type (MPAS_Alarm_type), pointer :: next => null() end type type MPAS_Clock_type integer :: direction integer :: nAlarms type (ESMF_Clock) :: c - type (MPAS_Alarm_type), pointer :: alarmListHead + type (MPAS_Alarm_type), pointer :: alarmListHead => null() end type diff --git a/src/framework/xml_stream_parser.c b/src/framework/xml_stream_parser.c index 64b243faed..973bfc1c47 100644 --- a/src/framework/xml_stream_parser.c +++ b/src/framework/xml_stream_parser.c @@ -25,7 +25,7 @@ /* * Interface routines for building streams at run-time; defined in mpas_stream_manager.F */ -void stream_mgr_create_stream_c(void *, const char *, int *, const char *, const char *, const char *, const char *, int *, int *, int *, int *, int *); +void stream_mgr_create_stream_c(void *, const char *, int *, const char *, const char *, const char *, const char *, const char *, const char *, int *, int *, int *, int *, int *); void mpas_stream_mgr_add_field_c(void *, const char *, const char *, const char *, int *); void mpas_stream_mgr_add_immutable_stream_fields_c(void *, const char *, const char *, const char *, int *); void mpas_stream_mgr_add_pool_c(void *, const char *, const char *, const char *, int *); @@ -415,6 +415,16 @@ int attribute_check(ezxml_t stream) fmt_err(msgbuf); return 1; } + if ( strstr(s_filename_intv, "input_interval") != NULL && strstr(s_input, "final_only") != NULL) { + snprintf(msgbuf, MSGSIZE, "stream \"%s\" cannot have a value of \"input_interval\" for the \"filename_interval\" attribute, when \"input_interval\" is set to \"final_only\".", s_name); + fmt_err(msgbuf); + return 1; + } + if ( strstr(s_filename_intv, "output_interval") != NULL && strstr(s_output, "final_only") != NULL) { + snprintf(msgbuf, MSGSIZE, "stream \"%s\" cannot have a value of \"output_interval\" for the \"filename_interval\" attribute, when \"output_interval\" is set to \"final_only\".", s_name); + fmt_err(msgbuf); + return 1; + } } @@ -1036,6 +1046,8 @@ void xml_stream_parser(char *fname, void *manager, int *mpi_comm, int *status) char fieldname[256]; char packages_local[256]; char interval_type[32]; + char interval_in_local[256]; + char interval_out_local[256]; FILE *fd; char msgbuf[MSGSIZE]; int itype; @@ -1119,23 +1131,22 @@ void xml_stream_parser(char *fname, void *manager, int *mpi_comm, int *status) /* Check for an input;output stream. Handle first as this is the most complicated case. */ if ( strstr(direction, "input") != NULL && strstr(direction, "output") != NULL ) { - /* If input interval is an interval (i.e. not initial_only or none) set filename_interval to the interval. */ - if ( strstr(interval_in, "initial_only") == NULL && strstr(interval_in, "none") == NULL ){ + /* If input interval is an interval (i.e. not initial_only/final_only or none) set filename_interval to the interval. */ + if ( strstr(interval_in, "initial_only") == NULL && strstr(interval_in, "final_only") == NULL && strstr(interval_in, "none") == NULL ){ filename_interval = interval_in2; - - /* If output interval is an interval (i.e. not initial_only or none) set filename_interval to the interval. */ - } else if ( strstr(interval_out, "initial_only") == NULL && strstr(interval_out, "none") == NULL ){ + /* If output interval is an interval (i.e. not initial_only/final_only or none) set filename_interval to the interval. */ + } else if ( strstr(interval_out, "initial_only") == NULL && strstr(interval_out, "final_only") == NULL && strstr(interval_out, "none") == NULL ){ filename_interval = interval_out2; } /* Check for an input stream. */ } else if ( strstr(direction, "input") != NULL ) { - if ( strstr(interval_in2, "initial_only") == NULL && strstr(interval_in2, "none") == NULL ){ + if ( strstr(interval_in, "initial_only") == NULL && strstr(interval_in, "final_only") == NULL && strstr(interval_in, "none") == NULL ){ filename_interval = interval_in2; } /* Check for an output stream. */ } else if ( strstr(direction, "output") != NULL ) { - if ( strstr(interval_out, "initial_only") == NULL && strstr(interval_out, "none") == NULL ){ + if ( strstr(interval_out, "initial_only") == NULL && strstr(interval_out, "final_only") == NULL && strstr(interval_out, "none") == NULL ){ filename_interval = interval_out2; } } @@ -1148,13 +1159,13 @@ void xml_stream_parser(char *fname, void *manager, int *mpi_comm, int *status) * to force it's value to be none as well. */ if ( strstr(filename_interval, "input_interval") != NULL ) { - if ( strstr(interval_in, "initial_only") == NULL && strstr(interval_in, "none") == NULL ) { + if ( strstr(interval_in, "initial_only") == NULL && strstr(interval_in, "final_only") == NULL && strstr(interval_in, "none") == NULL ) { filename_interval = interval_in2; } else { filename_interval = NULL; } } else if ( strstr(filename_interval, "output_interval") != NULL ) { - if ( strstr(interval_out, "initial_only") == NULL && strstr(interval_out, "none") == NULL ) { + if ( strstr(interval_out, "initial_only") == NULL && strstr(interval_out, "final_only") == NULL && strstr(interval_out, "none") == NULL ) { filename_interval = interval_out2; } else { filename_interval = NULL; @@ -1245,6 +1256,19 @@ void xml_stream_parser(char *fname, void *manager, int *mpi_comm, int *status) fprintf(stderr, " %-20s%s\n", "direction:", "none"); } + if (interval_in != NULL && (itype == 1 || itype == 3)) { + snprintf(interval_in_local, 256, "%s", interval_in); + } + else { + snprintf(interval_in_local, 256, "none"); + } + if (interval_out != NULL && (itype == 2 || itype == 3)) { + snprintf(interval_out_local, 256, "%s", interval_out); + } + else { + snprintf(interval_out_local, 256, "none"); + } + if (reference_time != NULL) { snprintf(ref_time_local, 256, "%s", reference_time); } @@ -1287,8 +1311,9 @@ void xml_stream_parser(char *fname, void *manager, int *mpi_comm, int *status) } } - stream_mgr_create_stream_c(manager, streamID, &itype, filename_template, filename_interval_string, ref_time_local, rec_intv_local, - &immutable, &iprec, &iclobber, &i_iotype, &err); + stream_mgr_create_stream_c(manager, streamID, &itype, filename_template, filename_interval_string, + interval_in_local, interval_out_local, ref_time_local, rec_intv_local, + &immutable, &iprec, &iclobber, &i_iotype, &err); if (err != 0) { *status = 1; return; @@ -1401,23 +1426,23 @@ void xml_stream_parser(char *fname, void *manager, int *mpi_comm, int *status) /* Check for an input;output stream. Handle first as this is the most complicated case. */ if ( strstr(direction, "input") != NULL && strstr(direction, "output") != NULL ) { - /* If input interval is an interval (i.e. not initial_only or none) set filename_interval to the interval. */ - if ( strstr(interval_in, "initial_only") == NULL && strstr(interval_in, "none") == NULL ){ + /* If input interval is an interval (i.e. not initial_only/final_only or none) set filename_interval to the interval. */ + if ( strstr(interval_in, "initial_only") == NULL && strstr(interval_in, "final_only") == NULL && strstr(interval_in, "none") == NULL ){ filename_interval = interval_in2; - /* If output interval is an interval (i.e. not initial_only or none) set filename_interval to the interval. */ - } else if ( strstr(interval_out, "initial_only") == NULL && strstr(interval_out, "none") == NULL ){ + /* If output interval is an interval (i.e. not initial_only/final_only or none) set filename_interval to the interval. */ + } else if ( strstr(interval_out, "initial_only") == NULL && strstr(interval_out, "final_only") == NULL && strstr(interval_out, "none") == NULL ){ filename_interval = interval_out2; } /* Check for an input stream. */ } else if ( strstr(direction, "input") != NULL ) { - if ( strstr(interval_in, "initial_only") == NULL && strstr(interval_in, "none") == NULL ){ + if ( strstr(interval_in, "initial_only") == NULL && strstr(interval_in, "final_only") == NULL && strstr(interval_in, "none") == NULL ){ filename_interval = interval_in2; } /* Check for an output stream. */ } else if ( strstr(direction, "output") != NULL ) { - if ( strstr(interval_out, "initial_only") == NULL && strstr(interval_out, "none") == NULL ){ + if ( strstr(interval_out, "initial_only") == NULL && strstr(interval_out, "final_only") == NULL && strstr(interval_out, "none") == NULL ){ filename_interval = interval_out2; } } @@ -1430,13 +1455,13 @@ void xml_stream_parser(char *fname, void *manager, int *mpi_comm, int *status) * to force it's value to be none as well. */ if ( strstr(filename_interval, "input_interval") != NULL ) { - if ( strstr(interval_in, "initial_only") == NULL && strstr(interval_in, "none") == NULL ) { + if ( strstr(interval_in, "initial_only") == NULL && strstr(interval_in, "final_only") == NULL && strstr(interval_in, "none") == NULL ) { filename_interval = interval_in2; } else { filename_interval = NULL; } } else if ( strstr(filename_interval, "output_interval") != NULL ) { - if ( strstr(interval_out, "initial_only") == NULL && strstr(interval_out, "none") == NULL ) { + if ( strstr(interval_out, "initial_only") == NULL && strstr(interval_out, "final_only") == NULL && strstr(interval_out, "none") == NULL ) { filename_interval = interval_out2; } else { filename_interval = NULL; @@ -1527,6 +1552,19 @@ void xml_stream_parser(char *fname, void *manager, int *mpi_comm, int *status) fprintf(stderr, " %-20s%s\n", "direction:", "none"); } + if (interval_in != NULL && (itype == 1 || itype == 3)) { + snprintf(interval_in_local, 256, "%s", interval_in); + } + else { + snprintf(interval_in_local, 256, "none"); + } + if (interval_out != NULL && (itype == 2 || itype == 3)) { + snprintf(interval_out_local, 256, "%s", interval_out); + } + else { + snprintf(interval_out_local, 256, "none"); + } + if (reference_time != NULL) { snprintf(ref_time_local, 256, "%s", reference_time); } @@ -1569,8 +1607,9 @@ void xml_stream_parser(char *fname, void *manager, int *mpi_comm, int *status) } } - stream_mgr_create_stream_c(manager, streamID, &itype, filename_template, filename_interval_string, ref_time_local, rec_intv_local, - &immutable, &iprec, &iclobber, &i_iotype, &err); + stream_mgr_create_stream_c(manager, streamID, &itype, filename_template, filename_interval_string, + interval_in_local, interval_out_local, ref_time_local, rec_intv_local, + &immutable, &iprec, &iclobber, &i_iotype, &err); if (err != 0) { *status = 1; return;