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;