!
! 1.The actual run length will be the sum of months,
! days, hours, minutes, and seconds. A run length of zero
! is not a valid option.
! 2.The run length must be an integral multiple of the coupling
! timestep dt_cpld.
!
!
!
use constants_mod, only: constants_init
use data_override_mod, only: data_override_init, data_override
use diag_manager_mod, only: diag_manager_init, register_diag_field, diag_manager_end
use field_manager_mod, only: field_manager_init
use fms_mod, only: fms_init, fms_end, open_namelist_file, check_nml_error
use fms_mod, only: close_file, file_exist, uppercase
use fms_io_mod, only: fms_io_exit
use mpp_domains_mod, only: domain2d, mpp_get_compute_domain
use mpp_io_mod, only: mpp_open, MPP_RDONLY, MPP_ASCII, MPP_OVERWR, MPP_APPEND, mpp_close, MPP_SINGLE
use mpp_mod, only: mpp_error, FATAL, mpp_pe, mpp_npes, mpp_set_current_pelist
use mpp_mod, only: stdlog, stdout, mpp_root_pe, mpp_clock_id
use mpp_mod, only: mpp_clock_begin, mpp_clock_end, MPP_CLOCK_SYNC
use mpp_mod, only: MPP_CLOCK_DETAILED, CLOCK_COMPONENT
use time_interp_external_mod, only: time_interp_external_init
use time_manager_mod, only: set_calendar_type, time_type, increment_time, increment_date
use time_manager_mod, only: set_time, set_date, get_time, get_date, month_name
use time_manager_mod, only: JULIAN, NOLEAP, THIRTY_DAY_MONTHS, NO_CALENDAR
use time_manager_mod, only: operator( <= ), operator( < ), operator( >= )
use time_manager_mod, only: operator( + ), operator( - ), operator( / )
use ocean_model_mod, only: ocean_model_init , update_ocean_model, ocean_model_end
use ocean_types_mod, only: ocean_data_type, ice_ocean_boundary_type
#ifdef PRISM
use ocean_prism_mod, only: ocean_prism_init, localComm, ocean_prism_terminate
#endif
implicit none
type (ocean_data_type) :: Ocean_sfc
type(ice_ocean_boundary_type), target :: Ice_ocean_boundary
! define some time types
type(time_type) :: Time_init ! initial time for experiment
type(time_type) :: Time_start ! start time for experiment
type(time_type) :: Time_end ! end time for experiment (as determined by dtts)
type(time_type) :: Run_len ! length of experiment
type(time_type) :: Time
type(time_type) :: Time_step_ocean
type(time_type) :: Time_step_coupled
character(len=17) :: calendar = 'julian'
integer :: dt_ocean = 3600
integer :: dt_cpld = 86400
integer :: num_cpld_calls = 0
integer :: num_ocean_calls = 0
integer :: nc, no
integer :: calendar_type=-1
integer :: date_init(6)=0, date(6)
integer :: years=0, months=0, days=0, hours=0, minutes=0, seconds=0
integer :: yr, mon, day, hr, min, sec
integer :: isc,iec,jsc,jec
integer :: unit, log_unit, io_status, ierr
integer :: memuse
integer :: flags=0, override_clock
integer :: nfields
character(len=256) :: version = ''
character(len=256) :: tag = ''
logical :: ocean_seg_start
logical :: ocean_seg_end
character(len=9) :: month
namelist /ocean_solo_nml/ date_init, calendar, months, days, hours, minutes, seconds, dt_cpld, dt_ocean
! initialize shared modules
#ifdef PRISM
call ocean_prism_init(ierr)
call fms_init(localComm)
#else
call fms_init()
#endif
call constants_init
flags = MPP_CLOCK_SYNC
! provide for namelist over-ride
unit = open_namelist_file('input.nml')
read (unit, ocean_solo_nml,iostat=io_status)
write (stdout(),'(/)')
write (stdout(),'(/47x,a/)') '======== MODEL BEING DRIVEN BY OCEAN_SOLO_MOD ========'
write (stdout(), ocean_solo_nml)
write (stdlog(), ocean_solo_nml)
ierr = check_nml_error(io_status,'ocean_solo_nml')
call close_file (unit)
write (stdlog(),'(/,80("="),/(a))') trim(version), trim(tag)
! set the calendar
select case( uppercase(trim(calendar)) )
case( 'JULIAN' )
calendar_type = JULIAN
case( 'NOLEAP' )
calendar_type = NOLEAP
case( 'THIRTY_DAY' )
calendar_type = THIRTY_DAY_MONTHS
case( 'NO_CALENDAR' )
calendar_type = NO_CALENDAR
case default
call mpp_error( FATAL, 'ocean_solo: ocean_solo_nml entry calendar must be one of JULIAN|NOLEAP|THIRTY_DAY|NO_CALENDAR.' )
end select
! get ocean_solo restart : this can override settings from namelist
if (file_exist('INPUT/ocean_solo.res')) then
call mpp_open(unit,'INPUT/ocean_solo.res',form=MPP_ASCII,action=MPP_RDONLY)
read(unit,*) calendar_type
read(unit,*) date_init
read(unit,*) date
call close_file(unit)
endif
call set_calendar_type (calendar_type)
!!$ initialize pelists for ocean ensembles set current pelist to ensemble member
!!$ need to call prior to diagnostics_init
!!$ code presently not supported (mjh)
!!$ call ocean_ensemble_init()
call field_manager_init(nfields)
call diag_manager_init()
call time_interp_external_init()
if (sum(date_init) <= 0) then
call mpp_error(FATAL,'==>Error from ocean_solo_mod: date_init must be set either in ocean_solo.res or in ocean_solo_nml')
else
Time_init = set_date(date_init(1),date_init(2), date_init(3), &
date_init(4),date_init(5),date_init(6))
endif
if (file_exist('INPUT/ocean_solo.res')) then
Time_start = set_date(date(1),date(2),date(3),date(4),date(5),date(6))
else
Time_start = Time_init
date = date_init
endif
Time_end = increment_date(Time_start, years, months, days, hours, minutes, seconds)
Run_len = Time_end - Time_start
Time_step_ocean = set_time(dt_ocean, 0)
Time_step_coupled = set_time(dt_cpld, 0)
num_cpld_calls = Run_len / Time_step_coupled
num_ocean_calls = Time_step_coupled / Time_step_ocean
Time = Time_start
call mpp_open (unit, 'time_stamp.out', form=MPP_ASCII, action=MPP_APPEND,threading=MPP_SINGLE)
month = month_name(date(2))
if ( mpp_pe() == mpp_root_pe() ) write (unit,'(6i4,2x,a3)') date, month(1:3)
call get_date (Time_end, date(1), date(2), date(3), date(4), date(5), date(6))
month = month_name(date(2))
if ( mpp_pe() == mpp_root_pe() ) write (unit,'(6i4,2x,a3)') date, month(1:3)
call close_file (unit)
call ocean_model_init(Ocean_sfc, Time_init, Time, Time_step_ocean )
call data_override_init(Ocean_domain_in = Ocean_sfc%domain)
override_clock = mpp_clock_id('Override', flags=flags,grain=CLOCK_COMPONENT)
call mpp_get_compute_domain(Ocean_sfc%domain, isc, iec, jsc, jec)
allocate ( Ice_ocean_boundary% u_flux (isc:iec,jsc:jec), &
Ice_ocean_boundary% v_flux (isc:iec,jsc:jec), &
Ice_ocean_boundary% t_flux (isc:iec,jsc:jec), &
Ice_ocean_boundary% q_flux (isc:iec,jsc:jec), &
Ice_ocean_boundary% salt_flux (isc:iec,jsc:jec), &
Ice_ocean_boundary% lw_flux (isc:iec,jsc:jec), &
Ice_ocean_boundary% sw_flux (isc:iec,jsc:jec), &
Ice_ocean_boundary% lprec (isc:iec,jsc:jec), &
Ice_ocean_boundary% fprec (isc:iec,jsc:jec), &
Ice_ocean_boundary% runoff (isc:iec,jsc:jec), &
Ice_ocean_boundary% calving (isc:iec,jsc:jec), &
Ice_ocean_boundary% p (isc:iec,jsc:jec))
Ice_ocean_boundary%u_flux = 0.0
Ice_ocean_boundary%v_flux = 0.0
Ice_ocean_boundary%t_flux = 0.0
Ice_ocean_boundary%q_flux = 0.0
Ice_ocean_boundary%salt_flux = 0.0
Ice_ocean_boundary%lw_flux = 0.0
Ice_ocean_boundary%sw_flux = 0.0
Ice_ocean_boundary%lprec = 0.0
Ice_ocean_boundary%fprec = 0.0
Ice_ocean_boundary%runoff = 0.0
Ice_ocean_boundary%calving = 0.0
Ice_ocean_boundary%p = 0.0
! loop over the coupled calls
do nc=1, num_cpld_calls
call mpp_clock_begin(override_clock)
call ice_ocn_bnd_from_data(Ice_ocean_boundary)
call mpp_clock_end(override_clock)
! loop over the ocean calls
do no=1, num_ocean_calls
ocean_seg_start = ( no .eq. 1 )
ocean_seg_end = ( no .eq. num_ocean_calls )
call update_ocean_model(Ice_ocean_boundary, Ocean_sfc, ocean_seg_start, ocean_seg_end, num_ocean_calls)
Time = Time + Time_step_ocean
enddo
enddo
! close some of the main components
call ocean_model_end(Ocean_sfc)
call diag_manager_end(Time)
! need to reset pelist before calling mpp_clock_end
call mpp_set_current_pelist()
! write restart file
call mpp_open( unit, 'RESTART/ocean_solo.res', nohdrs=.TRUE. )
if ( mpp_pe().EQ.mpp_root_pe() )then
write( unit, '(i6,8x,a)' )calendar_type, &
'(Calendar: no_calendar=0, thirty_day_months=1, julian=2, gregorian=3, noleap=4)'
call get_date(Time_init,yr,mon,day,hr,min,sec)
write( unit, '(6i6,8x,a)' )yr,mon,day,hr,min,sec, &
'Model start time: year, month, day, hour, minute, second'
call get_date(Time_end ,yr,mon,day,hr,min,sec)
write( unit, '(6i6,8x,a)' )yr,mon,day,hr,min,sec, &
'Current model time: year, month, day, hour, minute, second'
end if
call mpp_close(unit)
call fms_io_exit
call fms_end
#ifdef PRISM
call ocean_prism_terminate
#endif
contains
!====================================================================
! get forcing data from data_overide
subroutine ice_ocn_bnd_from_data(x)
type (ice_ocean_boundary_type) :: x
integer :: i,j
type(time_type) :: Time_next
Time_next = Time + Time_step_ocean
call data_override('OCN', 't_flux', x%t_flux , Time_next)
call data_override('OCN', 'u_flux', x%u_flux , Time_next)
call data_override('OCN', 'v_flux', x%v_flux , Time_next)
call data_override('OCN', 'q_flux', x%q_flux , Time_next)
call data_override('OCN', 'salt_flux', x%salt_flux, Time_next)
call data_override('OCN', 'lw_flux', x%lw_flux , Time_next)
call data_override('OCN', 'sw_flux', x%sw_flux , Time_next)
call data_override('OCN', 'lprec', x%lprec , Time_next)
call data_override('OCN', 'fprec', x%fprec , Time_next)
call data_override('OCN', 'runoff', x%runoff , Time_next)
call data_override('OCN', 'calving', x%calving , Time_next)
call data_override('OCN', 'p', x%p , Time_next)
end subroutine ice_ocn_bnd_from_data
end program main