MOM6
MOM_driver.F90
1 program mom_main
2 
3 ! This file is part of MOM6. See LICENSE.md for the license.
4 
5 !********+*********+*********+*********+*********+*********+*********+**
6 !* *
7 !* The Modular Ocean Model, version 6 *
8 !* MOM6 *
9 !* *
10 !* By Alistair Adcroft, Stephen Griffies and Robert Hallberg *
11 !* *
12 !* This file is the ocean-only driver for Version 6 of the Modular *
13 !* Ocean Model (MOM). A separate ocean interface for use with *
14 !* coupled models is provided in ocean_model_MOM.F90. These two *
15 !* drivers are kept in separate directories for convenience of code *
16 !* selection during compiling. This file orchestrates the calls to *
17 !* the MOM initialization routines, to the subroutine that steps *
18 !* the model, and coordinates the output and saving restarts. A *
19 !* description of all of the files that constitute MOM is found in *
20 !* the comments at the beginning of MOM.F90. The arguments of each *
21 !* subroutine are described where the subroutine is defined. *
22 !* *
23 !* Macros written all in capital letters are defined in MOM_memory.h. *
24 !* *
25 !********+*********+*********+*********+*********+*********+*********+**
26 
27  use mom_cpu_clock, only : cpu_clock_id, cpu_clock_begin, cpu_clock_end
28  use mom_cpu_clock, only : clock_component
29  use mom_diag_mediator, only : enable_averaging, disable_averaging, diag_mediator_end
30  use mom_diag_mediator, only : diag_ctrl, diag_mediator_close_registration
31  use mom, only : initialize_mom, step_mom, mom_control_struct, mom_end
32  use mom, only : extract_surface_state, finish_mom_initialization
33  use mom, only : get_mom_state_elements, mom_state_is_synchronized
34  use mom, only : step_offline
35  use mom_domains, only : mom_infra_init, mom_infra_end
36  use mom_error_handler, only : mom_error, mom_mesg, warning, fatal, is_root_pe
37  use mom_error_handler, only : calltree_enter, calltree_leave, calltree_waypoint
39  use mom_file_parser, only : close_param_file
40  use mom_forcing_type, only : forcing, mech_forcing, forcing_diagnostics
41  use mom_forcing_type, only : mech_forcing_diags, mom_forcing_chksum, mom_mech_forcing_chksum
42  use mom_get_input, only : directories
43  use mom_grid, only : ocean_grid_type
44  use mom_io, only : file_exists, open_file, close_file
45  use mom_io, only : check_nml_error, io_infra_init, io_infra_end
46  use mom_io, only : append_file, ascii_file, readonly_file, single_file
47  use mom_restart, only : mom_restart_cs, save_restart
48  use mom_string_functions,only : uppercase
49  use mom_surface_forcing, only : set_forcing, forcing_save_restart
50  use mom_surface_forcing, only : surface_forcing_init, surface_forcing_cs
51  use mom_time_manager, only : time_type, set_date, get_date
52  use mom_time_manager, only : real_to_time, time_type_to_real
53  use mom_time_manager, only : operator(+), operator(-), operator(*), operator(/)
54  use mom_time_manager, only : operator(>), operator(<), operator(>=)
55  use mom_time_manager, only : increment_date, set_calendar_type, month_name
56  use mom_time_manager, only : julian, gregorian, noleap, thirty_day_months
57  use mom_time_manager, only : no_calendar
60  use mom_variables, only : surface
62  use mom_write_cputime, only : write_cputime, mom_write_cputime_init
63  use mom_write_cputime, only : write_cputime_start_clock, write_cputime_cs
64 
65  use ensemble_manager_mod, only : ensemble_manager_init, get_ensemble_size
66  use ensemble_manager_mod, only : ensemble_pelist_setup
67  use mpp_mod, only : set_current_pelist => mpp_set_current_pelist
68  use time_interp_external_mod, only : time_interp_external_init
69  use fms_affinity_mod, only : fms_affinity_init, fms_affinity_set,fms_affinity_get
70 
71  use mom_ice_shelf, only : initialize_ice_shelf, ice_shelf_end, ice_shelf_cs
72  use mom_ice_shelf, only : shelf_calc_flux, add_shelf_forces, ice_shelf_save_restart
73 ! , add_shelf_flux_forcing, add_shelf_flux_IOB
74 
75  use mom_wave_interface, only: wave_parameters_cs, mom_wave_interface_init
76  use mom_wave_interface, only: mom_wave_interface_init_lite, update_surface_waves
77 
78  implicit none
79 
80 #include <MOM_memory.h>
81 
82  ! A structure with the driving mechanical surface forces
83  type(mech_forcing) :: forces
84  ! A structure containing pointers to the thermodynamic forcing fields
85  ! at the ocean surface.
86  type(forcing) :: fluxes
87 
88  ! A structure containing pointers to the ocean surface state fields.
89  type(surface) :: sfc_state
90 
91  ! A pointer to a structure containing metrics and related information.
92  type(ocean_grid_type), pointer :: grid
93  type(verticalGrid_type), pointer :: GV
94  ! A pointer to a structure containing dimensional unit scaling factors.
95  type(unit_scale_type), pointer :: US
96 
97  ! If .true., use the ice shelf model for part of the domain.
98  logical :: use_ice_shelf
99 
100  ! If .true., use surface wave coupling
101  logical :: use_waves = .false.
102 
103  ! This is .true. if incremental restart files may be saved.
104  logical :: permit_incr_restart = .true.
105 
106  integer :: ns
107 
108  ! nmax is the number of iterations after which to stop so that the
109  ! simulation does not exceed its CPU time limit. nmax is determined by
110  ! evaluating the CPU time used between successive calls to write_cputime.
111  ! Initially it is set to be very large.
112  integer :: nmax=2000000000
113 
114  ! A structure containing several relevant directory paths.
115  type(directories) :: dirs
116 
117  ! A suite of time types for use by MOM
118  type(time_type), target :: Time ! A copy of the ocean model's time.
119  ! Other modules can set pointers to this and
120  ! change it to manage diagnostics.
121  type(time_type) :: Master_Time ! The ocean model's master clock. No other
122  ! modules are ever given access to this.
123  type(time_type) :: Time1 ! The value of the ocean model's time at the
124  ! start of a call to step_MOM.
125  type(time_type) :: Start_time ! The start time of the simulation.
126  type(time_type) :: segment_start_time ! The start time of this run segment.
127  type(time_type) :: Time_end ! End time for the segment or experiment.
128  type(time_type) :: restart_time ! The next time to write restart files.
129  type(time_type) :: Time_step_ocean ! A time_type version of dt_forcing.
130 
131  real :: elapsed_time = 0.0 ! Elapsed time in this run [s].
132  logical :: elapsed_time_master ! If true, elapsed time is used to set the
133  ! model's master clock (Time). This is needed
134  ! if Time_step_ocean is not an exact
135  ! representation of dt_forcing.
136  real :: dt_forcing ! The coupling time step [s].
137  real :: dt ! The nominal baroclinic dynamics time step [s].
138  real :: dt_off ! Offline time step [s].
139  integer :: ntstep ! The number of baroclinic dynamics time steps
140  ! within dt_forcing.
141  real :: dt_therm ! The thermodynamic timestep [s]
142  real :: dt_dyn ! The actual dynamic timestep used [s]. The value of dt_dyn is
143  ! chosen so that dt_forcing is an integer multiple of dt_dyn.
144  real :: dtdia ! The diabatic timestep [s]
145  real :: t_elapsed_seg ! The elapsed time in this run segment [s]
146  integer :: n, n_max, nts, n_last_thermo
147  logical :: diabatic_first, single_step_call
148  type(time_type) :: Time2, time_chg
149 
150  integer :: Restart_control ! An integer that is bit-tested to determine whether
151  ! incremental restart files are saved and whether they
152  ! have a time stamped name. +1 (bit 0) for generic
153  ! files and +2 (bit 1) for time-stamped files. A
154  ! restart file is saved at the end of a run segment
155  ! unless Restart_control is negative.
156 
157  real :: Time_unit ! The time unit for the following input fields [s].
158  type(time_type) :: restint ! The time between saves of the restart file.
159  type(time_type) :: daymax ! The final day of the simulation.
160 
161  integer :: CPU_steps ! The number of steps between writing CPU time.
162  integer :: date_init(6)=0 ! The start date of the whole simulation.
163  integer :: date(6)=-1 ! Possibly the start date of this run segment.
164  integer :: years=0, months=0, days=0 ! These may determine the segment run
165  integer :: hours=0, minutes=0, seconds=0 ! length, if read from a namelist.
166  integer :: yr, mon, day, hr, mins, sec ! Temp variables for writing the date.
167  type(param_file_type) :: param_file ! The structure indicating the file(s)
168  ! containing all run-time parameters.
169  character(len=9) :: month
170  character(len=16) :: calendar = 'julian'
171  integer :: calendar_type=-1
172 
173  integer :: unit, io_status, ierr
174  integer :: ensemble_size, nPEs_per, ensemble_info(6)
175 
176  integer, dimension(0) :: atm_PElist, land_PElist, ice_PElist
177  integer, dimension(:), allocatable :: ocean_PElist
178  logical :: unit_in_use
179  integer :: initClock, mainClock, termClock
180 
181  logical :: debug ! If true, write verbose checksums for debugging purposes.
182  logical :: offline_tracer_mode ! If false, use the model in prognostic mode where
183  ! the barotropic and baroclinic dynamics, thermodynamics,
184  ! etc. are stepped forward integrated in time.
185  ! If true, then all of the above are bypassed with all
186  ! fields necessary to integrate only the tracer advection
187  ! and diffusion equation are read in from files stored from
188  ! a previous integration of the prognostic model
189 
190  type(MOM_control_struct), pointer :: MOM_CSp => null()
191  !> A pointer to the tracer flow control structure.
192  type(tracer_flow_control_CS), pointer :: &
193  tracer_flow_CSp => null() !< A pointer to the tracer flow control structure
194  type(surface_forcing_CS), pointer :: surface_forcing_CSp => null()
195  type(write_cputime_CS), pointer :: write_CPU_CSp => null()
196  type(ice_shelf_CS), pointer :: ice_shelf_CSp => null()
197  type(wave_parameters_cs), pointer :: waves_CSp => null()
198  type(MOM_restart_CS), pointer :: &
199  restart_CSp => null() !< A pointer to the restart control structure
200  !! that will be used for MOM restart files.
201  type(diag_ctrl), pointer :: &
202  diag => null() !< A pointer to the diagnostic regulatory structure
203  !-----------------------------------------------------------------------
204 
205  character(len=4), parameter :: vers_num = 'v2.0'
206 ! This include declares and sets the variable "version".
207 #include "version_variable.h"
208  character(len=40) :: mod_name = "MOM_main (MOM_driver)" ! This module's name.
209 
210  integer :: ocean_nthreads = 1
211  logical :: use_hyper_thread = .false.
212  integer :: omp_get_num_threads,omp_get_thread_num
213  namelist /ocean_solo_nml/ date_init, calendar, months, days, hours, minutes, seconds,&
214  ocean_nthreads, use_hyper_thread
215 
216  !=====================================================================
217 
218  call write_cputime_start_clock(write_cpu_csp)
219 
220  call mom_infra_init() ; call io_infra_init()
221 
222  ! Initialize the ensemble manager. If there are no settings for ensemble_size
223  ! in input.nml(ensemble.nml), these should not do anything. In coupled
224  ! configurations, this all occurs in the external driver.
225  call ensemble_manager_init() ; ensemble_info(:) = get_ensemble_size()
226  ensemble_size=ensemble_info(1) ; npes_per=ensemble_info(2)
227  if (ensemble_size > 1) then ! There are multiple ensemble members.
228  allocate(ocean_pelist(npes_per))
229  call ensemble_pelist_setup(.true., 0, npes_per, 0, 0, atm_pelist, ocean_pelist, &
230  land_pelist, ice_pelist)
231  call set_current_pelist(ocean_pelist)
232  deallocate(ocean_pelist)
233  endif
234 
235  ! These clocks are on the global pelist.
236  initclock = cpu_clock_id( 'Initialization' )
237  mainclock = cpu_clock_id( 'Main loop' )
238  termclock = cpu_clock_id( 'Termination' )
239  call cpu_clock_begin(initclock)
240 
241  call mom_mesg('======== Model being driven by MOM_driver ========', 2)
242  call calltree_waypoint("Program MOM_main, MOM_driver.F90")
243 
244  if (file_exists('input.nml')) then
245  ! Provide for namelist specification of the run length and calendar data.
246  call open_file(unit, 'input.nml', form=ascii_file, action=readonly_file)
247  read(unit, ocean_solo_nml, iostat=io_status)
248  call close_file(unit)
249  ierr = check_nml_error(io_status,'ocean_solo_nml')
250  if (years+months+days+hours+minutes+seconds > 0) then
251  if (is_root_pe()) write(*,ocean_solo_nml)
252  endif
253  endif
254 
255 !$ call fms_affinity_init
256 !$ call fms_affinity_set('OCEAN', use_hyper_thread, ocean_nthreads)
257 !$ call omp_set_num_threads(ocean_nthreads)
258 !$OMP PARALLEL
259 !$ write(6,*) "ocean_solo OMPthreading ", fms_affinity_get(), omp_get_thread_num(), omp_get_num_threads()
260 !$ call flush(6)
261 !$OMP END PARALLEL
262 
263  ! Read ocean_solo restart, which can override settings from the namelist.
264  if (file_exists(trim(dirs%restart_input_dir)//'ocean_solo.res')) then
265  call open_file(unit,trim(dirs%restart_input_dir)//'ocean_solo.res', &
266  form=ascii_file,action=readonly_file)
267  read(unit,*) calendar_type
268  read(unit,*) date_init
269  read(unit,*) date
270  call close_file(unit)
271  else
272  calendar = uppercase(calendar)
273  if (calendar(1:6) == 'JULIAN') then ; calendar_type = julian
274  elseif (calendar(1:9) == 'GREGORIAN') then ; calendar_type = gregorian
275  elseif (calendar(1:6) == 'NOLEAP') then ; calendar_type = noleap
276  elseif (calendar(1:10)=='THIRTY_DAY') then ; calendar_type = thirty_day_months
277  elseif (calendar(1:11)=='NO_CALENDAR') then; calendar_type = no_calendar
278  elseif (calendar(1:1) /= ' ') then
279  call mom_error(fatal,'MOM_driver: Invalid namelist value '//trim(calendar)//' for calendar')
280  else
281  call mom_error(fatal,'MOM_driver: No namelist value for calendar')
282  endif
283  endif
284  call set_calendar_type(calendar_type)
285 
286 
287  if (sum(date_init) > 0) then
288  start_time = set_date(date_init(1),date_init(2), date_init(3), &
289  date_init(4),date_init(5),date_init(6))
290  else
291  start_time = real_to_time(0.0)
292  endif
293 
294  call time_interp_external_init
295 
296  if (sum(date) >= 0) then
297  ! In this case, the segment starts at a time fixed by ocean_solo.res
298  segment_start_time = set_date(date(1),date(2),date(3),date(4),date(5),date(6))
299  time = segment_start_time
300  call initialize_mom(time, start_time, param_file, dirs, mom_csp, restart_csp, &
301  segment_start_time, offline_tracer_mode=offline_tracer_mode, &
302  diag_ptr=diag, tracer_flow_csp=tracer_flow_csp)
303  else
304  ! In this case, the segment starts at a time read from the MOM restart file
305  ! or left as Start_time by MOM_initialize.
306  time = start_time
307  call initialize_mom(time, start_time, param_file, dirs, mom_csp, restart_csp, &
308  offline_tracer_mode=offline_tracer_mode, diag_ptr=diag, &
309  tracer_flow_csp=tracer_flow_csp)
310  endif
311 
312  call get_mom_state_elements(mom_csp, g=grid, gv=gv, us=us, c_p_scaled=fluxes%C_p)
313  master_time = time
314 
315  call calltree_waypoint("done initialize_MOM")
316 
317  call extract_surface_state(mom_csp, sfc_state)
318 
319  call surface_forcing_init(time, grid, us, param_file, diag, &
320  surface_forcing_csp, tracer_flow_csp)
321  call calltree_waypoint("done surface_forcing_init")
322 
323  call get_param(param_file, mod_name, "ICE_SHELF", use_ice_shelf, &
324  "If true, enables the ice shelf model.", default=.false.)
325  if (use_ice_shelf) then
326  ! These arrays are not initialized in most solo cases, but are needed
327  ! when using an ice shelf
328  call initialize_ice_shelf(param_file, grid, time, ice_shelf_csp, &
329  diag, forces, fluxes)
330  endif
331 
332  call get_param(param_file,mod_name,"USE_WAVES",use_waves,&
333  "If true, enables surface wave modules.",default=.false.)
334  if (use_waves) then
335  call mom_wave_interface_init(time, grid, gv, us, param_file, waves_csp, diag)
336  else
337  call mom_wave_interface_init_lite(param_file)
338  endif
339 
340  segment_start_time = time
341  elapsed_time = 0.0
342 
343  ! Read all relevant parameters and write them to the model log.
344  call log_version(param_file, mod_name, version, "")
345  call get_param(param_file, mod_name, "DT", dt, fail_if_missing=.true.)
346  call get_param(param_file, mod_name, "DT_FORCING", dt_forcing, &
347  "The time step for changing forcing, coupling with other "//&
348  "components, or potentially writing certain diagnostics. "//&
349  "The default value is given by DT.", units="s", default=dt)
350  if (offline_tracer_mode) then
351  call get_param(param_file, mod_name, "DT_OFFLINE", dt_forcing, &
352  "Time step for the offline time step")
353  dt = dt_forcing
354  endif
355  ntstep = max(1,ceiling(dt_forcing/dt - 0.001))
356 
357  time_step_ocean = real_to_time(dt_forcing)
358  elapsed_time_master = (abs(dt_forcing - time_type_to_real(time_step_ocean)) > 1.0e-12*dt_forcing)
359  if (elapsed_time_master) &
360  call mom_mesg("Using real elapsed time for the master clock.", 2)
361 
362  ! Determine the segment end time, either from the namelist file or parsed input file.
363  call get_param(param_file, mod_name, "TIMEUNIT", time_unit, &
364  "The time unit for DAYMAX, ENERGYSAVEDAYS, and RESTINT.", &
365  units="s", default=86400.0)
366  if (years+months+days+hours+minutes+seconds > 0) then
367  time_end = increment_date(time, years, months, days, hours, minutes, seconds)
368  call mom_mesg('Segment run length determined from ocean_solo_nml.', 2)
369  call get_param(param_file, mod_name, "DAYMAX", daymax, timeunit=time_unit, &
370  default=time_end, do_not_log=.true.)
371  call log_param(param_file, mod_name, "DAYMAX", daymax, &
372  "The final time of the whole simulation, in units of "//&
373  "TIMEUNIT seconds. This also sets the potential end "//&
374  "time of the present run segment if the end time is "//&
375  "not set via ocean_solo_nml in input.nml.", &
376  timeunit=time_unit)
377  else
378  call get_param(param_file, mod_name, "DAYMAX", daymax, &
379  "The final time of the whole simulation, in units of "//&
380  "TIMEUNIT seconds. This also sets the potential end "//&
381  "time of the present run segment if the end time is "//&
382  "not set via ocean_solo_nml in input.nml.", &
383  timeunit=time_unit, fail_if_missing=.true.)
384  time_end = daymax
385  endif
386 
387  call get_param(param_file, mod_name, "SINGLE_STEPPING_CALL", single_step_call, &
388  "If true, advance the state of MOM with a single step "//&
389  "including both dynamics and thermodynamics. If false "//&
390  "the two phases are advanced with separate calls.", default=.true.)
391  call get_param(param_file, mod_name, "DT_THERM", dt_therm, &
392  "The thermodynamic and tracer advection time step. "//&
393  "Ideally DT_THERM should be an integer multiple of DT "//&
394  "and less than the forcing or coupling time-step, unless "//&
395  "THERMO_SPANS_COUPLING is true, in which case DT_THERM "//&
396  "can be an integer multiple of the coupling timestep. By "//&
397  "default DT_THERM is set to DT.", units="s", default=dt)
398  call get_param(param_file, mod_name, "DIABATIC_FIRST", diabatic_first, &
399  "If true, apply diabatic and thermodynamic processes, "//&
400  "including buoyancy forcing and mass gain or loss, "//&
401  "before stepping the dynamics forward.", default=.false.)
402 
403 
404  if (time >= time_end) call mom_error(fatal, &
405  "MOM_driver: The run has been started at or after the end time of the run.")
406 
407  call get_param(param_file, mod_name, "RESTART_CONTROL", restart_control, &
408  "An integer whose bits encode which restart files are "//&
409  "written. Add 2 (bit 1) for a time-stamped file, and odd "//&
410  "(bit 0) for a non-time-stamped file. A non-time-stamped "//&
411  "restart file is saved at the end of the run segment "//&
412  "for any non-negative value.", default=1)
413  call get_param(param_file, mod_name, "RESTINT", restint, &
414  "The interval between saves of the restart file in units "//&
415  "of TIMEUNIT. Use 0 (the default) to not save "//&
416  "incremental restart files at all.", default=real_to_time(0.0), &
417  timeunit=time_unit)
418  call get_param(param_file, mod_name, "WRITE_CPU_STEPS", cpu_steps, &
419  "The number of coupled timesteps between writing the cpu "//&
420  "time. If this is not positive, do not check cpu time, and "//&
421  "the segment run-length can not be set via an elapsed CPU time.", &
422  default=1000)
423  call get_param(param_file, "MOM", "DEBUG", debug, &
424  "If true, write out verbose debugging data.", &
425  default=.false., debuggingparam=.true.)
426 
427  call log_param(param_file, mod_name, "ELAPSED TIME AS MASTER", elapsed_time_master)
428 
429  if (cpu_steps > 0) &
430  call mom_write_cputime_init(param_file, dirs%output_directory, start_time, &
431  write_cpu_csp)
432 
433  ! Close the param_file. No further parsing of input is possible after this.
434  call close_param_file(param_file)
435  call diag_mediator_close_registration(diag)
436 
437  ! Write out a time stamp file.
438  if (calendar_type /= no_calendar) then
439  call open_file(unit, 'time_stamp.out', form=ascii_file, action=append_file, &
440  threading=single_file)
441  call get_date(time, date(1), date(2), date(3), date(4), date(5), date(6))
442  month = month_name(date(2))
443  if (is_root_pe()) write(unit,'(6i4,2x,a3)') date, month(1:3)
444  call get_date(time_end, date(1), date(2), date(3), date(4), date(5), date(6))
445  month = month_name(date(2))
446  if (is_root_pe()) write(unit,'(6i4,2x,a3)') date, month(1:3)
447  call close_file(unit)
448  endif
449 
450  if (cpu_steps > 0) call write_cputime(time, 0, write_cpu_csp)
451 
452  if (((.not.btest(restart_control,1)) .and. (.not.btest(restart_control,0))) &
453  .or. (restart_control < 0)) permit_incr_restart = .false.
454 
455  if (restint > real_to_time(0.0)) then
456  ! restart_time is the next integral multiple of restint.
457  restart_time = start_time + restint * &
458  (1 + ((time + time_step_ocean) - start_time) / restint)
459  else
460  ! Set the time so late that there is no intermediate restart.
461  restart_time = time_end + time_step_ocean
462  permit_incr_restart = .false.
463  endif
464 
465  call cpu_clock_end(initclock) !end initialization
466 
467  call cpu_clock_begin(mainclock) !begin main loop
468 
469  ns = 1
470  do while ((ns < nmax) .and. (time < time_end))
471  call calltree_enter("Main loop, MOM_driver.F90",ns)
472 
473  ! Set the forcing for the next steps.
474  if (.not. offline_tracer_mode) then
475  call set_forcing(sfc_state, forces, fluxes, time, time_step_ocean, grid, us, &
476  surface_forcing_csp)
477  endif
478  if (debug) then
479  call mom_mech_forcing_chksum("After set forcing", forces, grid, us, haloshift=0)
480  call mom_forcing_chksum("After set forcing", fluxes, grid, us, haloshift=0)
481  endif
482 
483  if (use_ice_shelf) then
484  call shelf_calc_flux(sfc_state, fluxes, time, dt_forcing, ice_shelf_csp)
485  call add_shelf_forces(grid, us, ice_shelf_csp, forces)
486  endif
487  fluxes%fluxes_used = .false.
488  fluxes%dt_buoy_accum = us%s_to_T*dt_forcing
489 
490  if (use_waves) then
491  call update_surface_waves(grid, gv, us, time, time_step_ocean, waves_csp)
492  endif
493 
494  if (ns==1) then
495  call finish_mom_initialization(time, dirs, mom_csp, restart_csp)
496  endif
497 
498  ! This call steps the model over a time dt_forcing.
499  time1 = master_time ; time = master_time
500  if (offline_tracer_mode) then
501  call step_offline(forces, fluxes, sfc_state, time1, dt_forcing, mom_csp)
502  elseif (single_step_call) then
503  call step_mom(forces, fluxes, sfc_state, time1, dt_forcing, mom_csp, waves=waves_csp)
504  else
505  n_max = 1 ; if (dt_forcing > dt) n_max = ceiling(dt_forcing/dt - 0.001)
506  dt_dyn = dt_forcing / real(n_max)
507 
508  nts = max(1,min(n_max,floor(dt_therm/dt_dyn + 0.001)))
509  n_last_thermo = 0
510 
511  time2 = time1 ; t_elapsed_seg = 0.0
512  do n=1,n_max
513  if (diabatic_first) then
514  if (modulo(n-1,nts)==0) then
515  dtdia = dt_dyn*min(ntstep,n_max-(n-1))
516  call step_mom(forces, fluxes, sfc_state, time2, dtdia, mom_csp, &
517  do_dynamics=.false., do_thermodynamics=.true., &
518  start_cycle=(n==1), end_cycle=.false., cycle_length=dt_forcing)
519  endif
520 
521  call step_mom(forces, fluxes, sfc_state, time2, dt_dyn, mom_csp, &
522  do_dynamics=.true., do_thermodynamics=.false., &
523  start_cycle=.false., end_cycle=(n==n_max), cycle_length=dt_forcing)
524  else
525  call step_mom(forces, fluxes, sfc_state, time2, dt_dyn, mom_csp, &
526  do_dynamics=.true., do_thermodynamics=.false., &
527  start_cycle=(n==1), end_cycle=.false., cycle_length=dt_forcing)
528 
529  if ((modulo(n,nts)==0) .or. (n==n_max)) then
530  dtdia = dt_dyn*(n - n_last_thermo)
531  ! Back up Time2 to the start of the thermodynamic segment.
532  if (n > n_last_thermo+1) &
533  time2 = time2 - real_to_time(dtdia - dt_dyn)
534  call step_mom(forces, fluxes, sfc_state, time2, dtdia, mom_csp, &
535  do_dynamics=.false., do_thermodynamics=.true., &
536  start_cycle=.false., end_cycle=(n==n_max), cycle_length=dt_forcing)
537  n_last_thermo = n
538  endif
539  endif
540 
541  t_elapsed_seg = t_elapsed_seg + dt_dyn
542  time2 = time1 + real_to_time(t_elapsed_seg)
543  enddo
544  endif
545 
546 ! Time = Time + Time_step_ocean
547 ! This is here to enable fractional-second time steps.
548  elapsed_time = elapsed_time + dt_forcing
549  if (elapsed_time > 2e9) then
550  ! This is here to ensure that the conversion from a real to an integer can be accurately
551  ! represented in long runs (longer than ~63 years). It will also ensure that elapsed time
552  ! does not lose resolution of order the timetype's resolution, provided that the timestep and
553  ! tick are larger than 10-5 seconds. If a clock with a finer resolution is used, a smaller
554  ! value would be required.
555  time_chg = real_to_time(elapsed_time)
556  segment_start_time = segment_start_time + time_chg
557  elapsed_time = elapsed_time - time_type_to_real(time_chg)
558  endif
559  if (elapsed_time_master) then
560  master_time = segment_start_time + real_to_time(elapsed_time)
561  else
562  master_time = master_time + time_step_ocean
563  endif
564  time = master_time
565 
566  if (cpu_steps > 0) then ; if (mod(ns, cpu_steps) == 0) then
567  call write_cputime(time, ns+ntstep-1, write_cpu_csp, nmax)
568  endif ; endif
569 
570  call mech_forcing_diags(forces, dt_forcing, grid, time, diag, surface_forcing_csp%handles)
571 
572  if (.not. offline_tracer_mode) then
573  if (fluxes%fluxes_used) then
574  call forcing_diagnostics(fluxes, sfc_state, grid, us, time, &
575  diag, surface_forcing_csp%handles)
576  else
577  call mom_error(fatal, "The solo MOM_driver is not yet set up to handle "//&
578  "thermodynamic time steps that are longer than the coupling timestep.")
579  endif
580  endif
581 
582 ! See if it is time to write out a restart file - timestamped or not.
583  if ((permit_incr_restart) .and. (fluxes%fluxes_used) .and. &
584  (time + (time_step_ocean/2) > restart_time)) then
585  if (btest(restart_control,1)) then
586  call save_restart(dirs%restart_output_dir, time, grid, &
587  restart_csp, .true., gv=gv)
588  call forcing_save_restart(surface_forcing_csp, grid, time, &
589  dirs%restart_output_dir, .true.)
590  if (use_ice_shelf) call ice_shelf_save_restart(ice_shelf_csp, time, &
591  dirs%restart_output_dir, .true.)
592  endif
593  if (btest(restart_control,0)) then
594  call save_restart(dirs%restart_output_dir, time, grid, &
595  restart_csp, gv=gv)
596  call forcing_save_restart(surface_forcing_csp, grid, time, &
597  dirs%restart_output_dir)
598  if (use_ice_shelf) call ice_shelf_save_restart(ice_shelf_csp, time, &
599  dirs%restart_output_dir)
600  endif
601  restart_time = restart_time + restint
602  endif
603 
604  ns = ns + ntstep
605  call calltree_leave("Main loop")
606  enddo
607 
608  call cpu_clock_end(mainclock)
609  call cpu_clock_begin(termclock)
610  if (restart_control>=0) then
611  if (.not.mom_state_is_synchronized(mom_csp)) &
612  call mom_error(warning, "End of MOM_main reached with inconsistent "//&
613  "dynamics and advective times. Additional restart fields "//&
614  "that have not been coded yet would be required for reproducibility.")
615  if (.not.fluxes%fluxes_used .and. .not.offline_tracer_mode) call mom_error(fatal, &
616  "End of MOM_main reached with unused buoyancy fluxes. "//&
617  "For conservation, the ocean restart files can only be "//&
618  "created after the buoyancy forcing is applied.")
619 
620  call save_restart(dirs%restart_output_dir, time, grid, restart_csp, gv=gv)
621  if (use_ice_shelf) call ice_shelf_save_restart(ice_shelf_csp, time, &
622  dirs%restart_output_dir)
623  ! Write ocean solo restart file.
624  call open_file(unit, trim(dirs%restart_output_dir)//'ocean_solo.res', nohdrs=.true.)
625  if (is_root_pe())then
626  write(unit, '(i6,8x,a)') calendar_type, &
627  '(Calendar: no_calendar=0, thirty_day_months=1, julian=2, gregorian=3, noleap=4)'
628 
629  call get_date(start_time, yr, mon, day, hr, mins, sec)
630  write(unit, '(6i6,8x,a)') yr, mon, day, hr, mins, sec, &
631  'Model start time: year, month, day, hour, minute, second'
632  call get_date(time, yr, mon, day, hr, mins, sec)
633  write(unit, '(6i6,8x,a)') yr, mon, day, hr, mins, sec, &
634  'Current model time: year, month, day, hour, minute, second'
635  endif
636  call close_file(unit)
637  endif
638 
639  if (is_root_pe()) then
640  do unit=10,1967
641  INQUIRE(unit,opened=unit_in_use)
642  if (.not.unit_in_use) exit
643  enddo
644  open(unit,file="exitcode",form="FORMATTED",status="REPLACE",action="WRITE")
645  if (time < daymax) then
646  write(unit,*) 9
647  else
648  write(unit,*) 0
649  endif
650  close(unit)
651  endif
652 
653  call calltree_waypoint("End MOM_main")
654  call diag_mediator_end(time, diag, end_diag_manager=.true.)
655  if (cpu_steps > 0) call write_cputime(time, ns-1, write_cpu_csp, call_end=.true.)
656  call cpu_clock_end(termclock)
657 
658  call io_infra_end ; call mom_infra_end
659 
660  call mom_end(mom_csp)
661  if (use_ice_shelf) call ice_shelf_end(ice_shelf_csp)
662 
663 end program mom_main
mom_time_manager
Wraps the FMS time manager functions.
Definition: MOM_time_manager.F90:2
mom_forcing_type::mech_forcing
Structure that contains pointers to the mechanical forcing at the surface used to drive the liquid oc...
Definition: MOM_forcing_type.F90:204
mom_variables::surface
Pointers to various fields which may be used describe the surface state of MOM, and which will be ret...
Definition: MOM_variables.F90:41
mom_write_cputime
A module to monitor the overall CPU time used by MOM6 and project when to stop the model.
Definition: MOM_write_cputime.F90:2
mom_ice_shelf
Implements the thermodynamic aspects of ocean / ice-shelf interactions, along with a crude placeholde...
Definition: MOM_ice_shelf.F90:4
mom_verticalgrid
Provides a transparent vertical ocean grid type and supporting routines.
Definition: MOM_verticalGrid.F90:2
mom_surface_forcing::surface_forcing_cs
Structure containing pointers to the forcing fields that may be used to drive MOM....
Definition: MOM_surface_forcing.F90:69
mom_file_parser::log_version
An overloaded interface to log version information about modules.
Definition: MOM_file_parser.F90:109
mom_diag_mediator
The subroutines here provide convenient wrappers to the fms diag_manager interfaces with additional d...
Definition: MOM_diag_mediator.F90:3
mom_get_input::directories
Container for paths and parameter file names.
Definition: MOM_get_input.F90:20
mom_string_functions
Handy functions for manipulating strings.
Definition: MOM_string_functions.F90:2
mom::mom_control_struct
Control structure for the MOM module, including the variables that describe the state of the ocean.
Definition: MOM.F90:165
mom_file_parser::param_file_type
A structure that can be parsed to read and document run-time parameters.
Definition: MOM_file_parser.F90:54
mom_file_parser::get_param
An overloaded interface to read and log the values of various types of parameters.
Definition: MOM_file_parser.F90:102
mom_io
This module contains I/O framework code.
Definition: MOM_io.F90:2
mom_restart::mom_restart_cs
A restart registry and the control structure for restarts.
Definition: MOM_restart.F90:75
mom_get_input
Reads the only Fortran name list needed to boot-strap the model.
Definition: MOM_get_input.F90:6
mom_unit_scaling::unit_scale_type
Describes various unit conversion factors.
Definition: MOM_unit_scaling.F90:14
mom_forcing_type
This module implements boundary forcing for MOM6.
Definition: MOM_forcing_type.F90:2
mom_wave_interface
Interface for surface waves.
Definition: MOM_wave_interface.F90:2
mom_wave_interface::wave_parameters_cs
Container for all surface wave related parameters.
Definition: MOM_wave_interface.F90:47
mom_ice_shelf::ice_shelf_cs
Control structure that contains ice shelf parameters and diagnostics handles.
Definition: MOM_ice_shelf.F90:72
mom_surface_forcing
Functions that calculate the surface wind stresses and fluxes of buoyancy or temperature/salinity and...
Definition: MOM_surface_forcing.F90:8
mom_verticalgrid::verticalgrid_type
Describes the vertical ocean grid, including unit conversion factors.
Definition: MOM_verticalGrid.F90:24
mom_restart
The MOM6 facility for reading and writing restart files, and querying what has been read.
Definition: MOM_restart.F90:2
mom_domains
Describes the decomposed MOM domain and has routines for communications across PEs.
Definition: MOM_domains.F90:2
mom_variables
Provides transparent structures with groups of MOM6 variables and supporting routines.
Definition: MOM_variables.F90:2
mom_cpu_clock
Wraps the MPP cpu clock functions.
Definition: MOM_cpu_clock.F90:2
mom_file_parser
The MOM6 facility to parse input files for runtime parameters.
Definition: MOM_file_parser.F90:2
mom_tracer_flow_control
Orchestrates the registration and calling of tracer packages.
Definition: MOM_tracer_flow_control.F90:2
mom_grid
Provides the ocean grid type.
Definition: MOM_grid.F90:2
mom_unit_scaling
Provides a transparent unit rescaling type to facilitate dimensional consistency testing.
Definition: MOM_unit_scaling.F90:2
mom_tracer_flow_control::tracer_flow_control_cs
The control structure for orchestrating the calling of tracer packages.
Definition: MOM_tracer_flow_control.F90:73
mom
The central module of the MOM6 ocean model.
Definition: MOM.F90:2
mom_forcing_type::forcing
Structure that contains pointers to the boundary forcing used to drive the liquid ocean simulated by ...
Definition: MOM_forcing_type.F90:66
mom_io::file_exists
Indicate whether a file exists, perhaps with domain decomposition.
Definition: MOM_io.F90:68
mom_write_cputime::write_cputime_cs
A control structure that regulates the writing of CPU time.
Definition: MOM_write_cputime.F90:22
mom_file_parser::log_param
An overloaded interface to log the values of various types of parameters.
Definition: MOM_file_parser.F90:96
mom_error_handler
Routines for error handling and I/O management.
Definition: MOM_error_handler.F90:2
mom_grid::ocean_grid_type
Ocean grid type. See mom_grid for details.
Definition: MOM_grid.F90:26
mom_diag_mediator::diag_ctrl
The following data type a list of diagnostic fields an their variants, as well as variables that cont...
Definition: MOM_diag_mediator.F90:240
mom_file_parser::read_param
An overloaded interface to read various types of parameters.
Definition: MOM_file_parser.F90:90