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
Pointers to various fields which may be used describe the surface state of MOM, and which will be ret...
Wraps the FMS time manager functions.
This module implements boundary forcing for MOM6.
A control structure that regulates the writing of CPU time.
Ocean grid type. See mom_grid for details.
Definition: MOM_grid.F90:26
Structure containing pointers to the forcing fields that may be used to drive MOM. All fluxes are positive into the ocean.
The central module of the MOM6 ocean model.
Definition: MOM.F90:2
The following data type a list of diagnostic fields an their variants, as well as variables that cont...
Reads the only Fortran name list needed to boot-strap the model.
A structure that can be parsed to read and document run-time parameters.
Provides the ocean grid type.
Definition: MOM_grid.F90:2
A module to monitor the overall CPU time used by MOM6 and project when to stop the model...
Wraps the MPP cpu clock functions.
Functions that calculate the surface wind stresses and fluxes of buoyancy or temperature/salinity and...
This module contains I/O framework code.
Definition: MOM_io.F90:2
The MOM6 facility to parse input files for runtime parameters.
An overloaded interface to log the values of various types of parameters.
Orchestrates the registration and calling of tracer packages.
Structure that contains pointers to the mechanical forcing at the surface used to drive the liquid oc...
Interface for surface waves.
Implements the thermodynamic aspects of ocean / ice-shelf interactions, along with a crude placeholde...
A restart registry and the control structure for restarts.
Definition: MOM_restart.F90:75
Describes various unit conversion factors.
Provides a transparent unit rescaling type to facilitate dimensional consistency testing.
Describes the decomposed MOM domain and has routines for communications across PEs.
Definition: MOM_domains.F90:2
The subroutines here provide convenient wrappers to the fms diag_manager interfaces with additional d...
Routines for error handling and I/O management.
Control structure for the MOM module, including the variables that describe the state of the ocean...
Definition: MOM.F90:165
The MOM6 facility for reading and writing restart files, and querying what has been read...
Definition: MOM_restart.F90:2
The control structure for orchestrating the calling of tracer packages.
Container for all surface wave related parameters.
Structure that contains pointers to the boundary forcing used to drive the liquid ocean simulated by ...
An overloaded interface to log version information about modules.
Describes the vertical ocean grid, including unit conversion factors.
Indicate whether a file exists, perhaps with domain decomposition.
Definition: MOM_io.F90:68
Control structure that contains ice shelf parameters and diagnostics handles.
An overloaded interface to read various types of parameters.
Container for paths and parameter file names.
Handy functions for manipulating strings.
Provides a transparent vertical ocean grid type and supporting routines.
Provides transparent structures with groups of MOM6 variables and supporting routines.
An overloaded interface to read and log the values of various types of parameters.