← back to index

config_src/drivers/solo_driver/MOM_driver.F90

portedportable, not yet portedexecuted, not portableexecutable, not hit by this run

1! This file is part of MOM6, the Modular Ocean Model version 6.
2! See the LICENSE file for licensing information.
3! SPDX-License-Identifier: Apache-2.0
4
52program MOM6
6
7!********+*********+*********+*********+*********+*********+*********+**
8!* *
9!* The Modular Ocean Model, version 6 *
10!* MOM6 *
11!* *
12!* By Alistair Adcroft, Stephen Griffies and Robert Hallberg *
13!* *
14!* This file is the ocean-only driver for Version 6 of the Modular *
15!* Ocean Model (MOM). A separate ocean interface for use with *
16!* coupled models is provided in ocean_model_MOM.F90. These two *
17!* drivers are kept in separate directories for convenience of code *
18!* selection during compiling. This file orchestrates the calls to *
19!* the MOM initialization routines, to the subroutine that steps *
20!* the model, and coordinates the output and saving restarts. A *
21!* description of all of the files that constitute MOM is found in *
22!* the comments at the beginning of MOM.F90. The arguments of each *
23!* subroutine are described where the subroutine is defined. *
24!* *
25!* Macros written all in capital letters are defined in MOM_memory.h. *
26!* *
27!********+*********+*********+*********+*********+*********+*********+**
28
291 use MOM_cpu_clock, only : cpu_clock_id, cpu_clock_begin, cpu_clock_end
30 use MOM_cpu_clock, only : CLOCK_COMPONENT
31 use MOM_data_override, only : data_override_init
32 use MOM_diag_mediator, only : diag_mediator_end, diag_ctrl, diag_mediator_close_registration
33 use MOM_diag_manager_infra, only : diag_manager_set_time_end_infra
34 use MOM, only : initialize_MOM, step_MOM, MOM_control_struct, MOM_end
35 use MOM, only : extract_surface_state, finish_MOM_initialization
36 use MOM, only : get_MOM_state_elements, MOM_state_is_synchronized
37 use MOM, only : step_offline
38 use MOM, only : save_MOM_restart
39 use MOM_coms, only : Set_PElist
40 use MOM_domains, only : MOM_infra_init, MOM_infra_end, set_MOM_thread_affinity
41 use MOM_ensemble_manager, only : ensemble_manager_init, get_ensemble_size
42 use MOM_ensemble_manager, only : ensemble_pelist_setup
43 use MOM_error_handler, only : MOM_error, MOM_mesg, WARNING, FATAL, is_root_pe
44 use MOM_error_handler, only : callTree_enter, callTree_leave, callTree_waypoint
45 use MOM_file_parser, only : read_param, get_param, log_param, log_version, param_file_type
46 use MOM_file_parser, only : close_param_file
47 use MOM_forcing_type, only : forcing, mech_forcing, forcing_diagnostics
48 use MOM_forcing_type, only : mech_forcing_diags, MOM_forcing_chksum, MOM_mech_forcing_chksum
49 use MOM_get_input, only : get_MOM_input, directories
50 use MOM_grid, only : ocean_grid_type
51 use MOM_ice_shelf, only : initialize_ice_shelf, ice_shelf_end, ice_shelf_CS
52 use MOM_ice_shelf, only : shelf_calc_flux, add_shelf_forces, ice_shelf_save_restart
53 use MOM_ice_shelf, only : initialize_ice_shelf_fluxes, initialize_ice_shelf_forces
54 use MOM_ice_shelf, only : ice_shelf_query, adjust_ice_sheet_frazil
55 use MOM_ice_shelf_initialize, only : initialize_ice_SMB
56 use MOM_interpolate, only : time_interp_external_init
57 use MOM_io, only : file_exists, open_ASCII_file, close_file
58 use MOM_io, only : check_nml_error, io_infra_init, io_infra_end
59 use MOM_io, only : APPEND_FILE, READONLY_FILE
60 use MOM_string_functions,only : uppercase
61 use MOM_surface_forcing, only : set_forcing, forcing_save_restart
62 use MOM_surface_forcing, only : surface_forcing_init, surface_forcing_CS
63 use MOM_time_manager, only : time_type, set_date, get_date, real_to_time, time_to_real
64 use MOM_time_manager, only : operator(+), operator(-), operator(*), operator(/)
65 use MOM_time_manager, only : operator(>), operator(<), operator(>=)
66 use MOM_time_manager, only : increment_date, set_calendar_type, month_name
67 use MOM_time_manager, only : JULIAN, GREGORIAN, NOLEAP, THIRTY_DAY_MONTHS, NO_CALENDAR
68 use MOM_tracer_flow_control, only : tracer_flow_control_CS
69 use MOM_unit_scaling, only : unit_scale_type
70 use MOM_variables, only : surface
71 use MOM_verticalGrid, only : verticalGrid_type
72 use MOM_wave_interface, only : wave_parameters_CS, MOM_wave_interface_init
73 use MOM_wave_interface, only : Update_Surface_Waves
74 use MOM_write_cputime, only : write_cputime, MOM_write_cputime_init
75 use MOM_write_cputime, only : write_cputime_start_clock, write_cputime_CS
76
77 implicit none
78
79#include <MOM_memory.h>
80
81 ! A structure with the driving mechanical surface forces
82 type(mech_forcing) :: forces
83 ! A structure containing pointers to the thermodynamic forcing fields
84 ! at the ocean surface.
85 type(forcing) :: fluxes
86 ! A structure containing pointers to the ocean surface state fields.
871 type(surface) :: sfc_state
88
89 ! A pointer to a structure containing metrics and related information.
90 type(ocean_grid_type), pointer :: grid => NULL()
91 type(verticalGrid_type), pointer :: GV => NULL()
92 ! A pointer to a structure containing dimensional unit scaling factors.
93 type(unit_scale_type), pointer :: US => NULL()
94
95 ! If .true., use the ice shelf model for part of the domain.
96 logical :: use_ice_shelf = .false.
97
98 ! If .true., use surface wave coupling
99 logical :: use_waves = .false.
100
101 ! This is .true. if incremental restart files may be saved.
102 logical :: permit_incr_restart = .true.
103
104 ! nmax is the number of iterations after which to stop so that the
105 ! simulation does not exceed its CPU time limit. nmax is determined by
106 ! evaluating the CPU time used between successive calls to write_cputime.
107 ! Initially it is set to be very large.
108 integer :: nmax=2000000000
109
110 ! A structure containing several relevant directory paths.
111 type(directories) :: dirs
112
113 ! A suite of time types for use by MOM
114 type(time_type), target :: Time ! A copy of the ocean model's time.
115 ! Other modules can set pointers to this and
116 ! change it to manage diagnostics.
117 type(time_type) :: Master_Time ! The ocean model's master clock. No other
118 ! modules are ever given access to this.
119 type(time_type) :: Time1 ! The value of the ocean model's time at the
120 ! start of a call to step_MOM.
121 type(time_type) :: Start_time ! The start time of the simulation.
122 type(time_type) :: segment_start_time ! The start time of this run segment.
123 type(time_type) :: Time_end ! End time for the segment or experiment.
124 type(time_type) :: restart_time ! The next time to write restart files.
125 type(time_type) :: Time_step_ocean ! A time_type version of dt_forcing.
126 logical :: segment_start_time_set ! True if segment_start_time has been set to a valid value.
127
128 real :: elapsed_time = 0.0 ! Elapsed time in this run [T ~> s].
129 logical :: elapsed_time_master ! If true, elapsed time is used to set the model's master
130 ! clock (Time). This is needed if Time_step_ocean is not
131 ! an exact representation of dt_forcing.
132 real :: dt_forcing ! The coupling time step [T ~> s].
133 real :: dt ! The nominal baroclinic dynamics time step [T ~> s].
134 integer :: ntstep ! The number of baroclinic dynamics time steps within dt_forcing.
135 real :: dt_therm ! The thermodynamic timestep [T ~> s]
136 real :: dt_dyn ! The actual dynamic timestep used [T ~> s]. The value of dt_dyn
137 ! is chosen so that dt_forcing is an integer multiple of dt_dyn.
138 real :: dtdia ! The diabatic timestep [T ~> s]
139 real :: t_elapsed_seg ! The elapsed time in this run segment [T ~> s]
140 integer :: n, ns, n_max, nts, n_last_thermo
141 logical :: diabatic_first, single_step_call, initialize_smb
142 type(time_type) :: Time2, time_chg ! Temporary time variables
143
144 integer :: Restart_control ! An integer that is bit-tested to determine whether
145 ! incremental restart files are saved and whether they
146 ! have a time stamped name. +1 (bit 0) for generic
147 ! files and +2 (bit 1) for time-stamped files. A
148 ! restart file is saved at the end of a run segment
149 ! unless Restart_control is negative.
150
151 real :: Time_unit ! The time unit for the following input fields [s].
152 type(time_type) :: restint ! The time between saves of the restart file.
153 type(time_type) :: daymax ! The final day of the simulation.
154
155 integer :: CPU_steps ! The number of steps between writing CPU time.
156 integer :: date(6) ! Possibly the start date of this run segment.
1576 type(param_file_type) :: param_file ! The structure indicating the file(s)
158 ! containing all run-time parameters.
159
160 integer :: calendar_type=-1 ! A coded integer indicating the calendar type.
161
162 integer :: unit, io_status, ierr
163 integer :: initClock, mainClock, termClock
164
165 logical :: debug ! If true, write verbose checksums for debugging purposes.
166 logical :: offline_tracer_mode ! If false, use the model in prognostic mode where
167 ! the barotropic and baroclinic dynamics, thermodynamics,
168 ! etc. are stepped forward integrated in time.
169 ! If true, then all of the above are bypassed with all
170 ! fields necessary to integrate only the tracer advection
171 ! and diffusion equation are read in from files stored from
172 ! a previous integration of the prognostic model
173
174179 type(MOM_control_struct) :: MOM_CSp !< The control structure with all the MOM6 internal types,
175 !! parameters and variables
176 type(tracer_flow_control_CS), pointer :: &
177 tracer_flow_CSp => NULL() !< A pointer to the tracer flow control structure
178 type(surface_forcing_CS), pointer :: surface_forcing_CSp => NULL()
179 type(write_cputime_CS), pointer :: write_CPU_CSp => NULL()
180 type(ice_shelf_CS), pointer :: ice_shelf_CSp => NULL()
181 logical :: override_shelf_fluxes !< If true, and shelf dynamics are active,
182 !! the data_override feature is enabled (only for MOSAIC grid types)
183 type(wave_parameters_cs), pointer :: waves_CSp => NULL()
184 type(diag_ctrl), pointer :: &
185 diag => NULL() !< A pointer to the diagnostic regulatory structure
186 !-----------------------------------------------------------------------
187
188 character(len=4), parameter :: vers_num = 'v2.0'
189 ! This include declares and sets the variable "version".
190# include "version_variable.h"
191 character(len=40) :: mod_name = "MOM_main (MOM_driver)" ! This module's name.
192
193 ! These are the variables that might be read via the namelist capability.
194 integer :: date_init(6)=0 ! The start date of the whole simulation.
195 character(len=16) :: calendar = 'julian' ! The name of the calendar type.
196 integer :: years=0, months=0, days=0 ! These may determine the segment run
197 integer :: hours=0, minutes=0, seconds=0 ! length, if read from a namelist.
198 integer :: ocean_nthreads = 1
199 logical :: use_hyper_thread = .false.
200 namelist /ocean_solo_nml/ date_init, calendar, months, days, hours, minutes, seconds, &
201 ocean_nthreads, use_hyper_thread
202
203 !=====================================================================
204
2051 call write_cputime_start_clock(write_CPU_CSp)
206
2071 call MOM_infra_init() ; call io_infra_init()
208
209 !allocate(forces,fluxes,sfc_state)
210
211 ! Initialize the ensemble manager based on settings in input.nml(ensemble.nml).
2121 call initialize_ocean_only_ensembles()
213
214 ! These clocks are on the global pelist.
2151 initClock = cpu_clock_id( 'Initialization' )
2161 mainClock = cpu_clock_id( 'Main loop' )
2171 termClock = cpu_clock_id( 'Termination' )
2181 call cpu_clock_begin(initClock)
219
2201 call MOM_mesg('======== Model being driven by MOM_driver ========', 2)
2211 call callTree_waypoint("Program MOM_main, MOM_driver.F90")
222
2231 if (file_exists('input.nml')) then
224 ! Provide for namelist specification of the run length and calendar data.
2251 call open_ASCII_file(unit, 'input.nml', action=READONLY_FILE)
2261 read(unit, ocean_solo_nml, iostat=io_status)
2271 call close_file(unit)
2281 ierr = check_nml_error(io_status,'ocean_solo_nml')
2291 if (is_root_pe() .and. (years+months+days+hours+minutes+seconds > 0)) write(*,ocean_solo_nml)
230 endif
231
232 ! This call sets the number and affinity of threads with openMP.
233 !$ call set_MOM_thread_affinity(ocean_nthreads, use_hyper_thread)
234
235 ! This call is required to initiate dirs%restart_input_dir for ocean_solo.res
236 ! The contents of dirs will be reread in initialize_MOM.
2371 call get_MOM_input(dirs=dirs)
238
2391 segment_start_time_set = .false.
240 ! Read ocean_solo restart, which can override settings from the namelist.
2411 if (file_exists(trim(dirs%restart_input_dir)//'ocean_solo.res')) then
2420 date(:) = -1
2430 call open_ASCII_file(unit, trim(dirs%restart_input_dir)//'ocean_solo.res', action=READONLY_FILE)
2440 read(unit,*) calendar_type
2450 read(unit,*) date_init
2460 read(unit,*) date
2470 call close_file(unit)
248
2490 call set_calendar_type(calendar_type)
2500 if (sum(date) >= 0) then
251 ! In this case, the segment starts at a time fixed by ocean_solo.res
2520 segment_start_time = set_date(date(1), date(2), date(3), date(4), date(5), date(6))
2530 segment_start_time_set = .true.
254 endif
255 else
2561 calendar = uppercase(calendar)
2571 if (calendar(1:6) == 'JULIAN') then ; calendar_type = JULIAN
2580 elseif (calendar(1:9) == 'GREGORIAN') then ; calendar_type = GREGORIAN
2590 elseif (calendar(1:6) == 'NOLEAP') then ; calendar_type = NOLEAP
2600 elseif (calendar(1:10)=='THIRTY_DAY') then ; calendar_type = THIRTY_DAY_MONTHS
2610 elseif (calendar(1:11)=='NO_CALENDAR') then ; calendar_type = NO_CALENDAR
2620 elseif (calendar(1:1) /= ' ') then
2630 call MOM_error(FATAL,'MOM_driver: Invalid namelist value '//trim(calendar)//' for calendar')
264 else
2650 call MOM_error(FATAL,'MOM_driver: No namelist value for calendar')
266 endif
2671 call set_calendar_type(calendar_type)
268 endif
269
270
2717 if (sum(date_init) > 0) then
272 Start_time = set_date(date_init(1), date_init(2), date_init(3), &
2730 date_init(4), date_init(5), date_init(6))
274 else
2751 Start_time = real_to_time(0.0)
276 endif
277
2781 call time_interp_external_init()
279
280 ! Call initialize MOM with an optional Ice Shelf CS which, if present triggers
281 ! initialization of ice shelf parameters and arrays.
282 !$omp target enter data map(alloc: MOM_CSp)
2831 if (segment_start_time_set) then
284 ! In this case, the segment starts at a time fixed by ocean_solo.res
2850 Time = segment_start_time
286 call initialize_MOM(Time, Start_time, param_file, dirs, MOM_CSp, &
287 segment_start_time, offline_tracer_mode=offline_tracer_mode, &
288 diag_ptr=diag, tracer_flow_CSp=tracer_flow_CSp, ice_shelf_CSp=ice_shelf_CSp, &
2890 waves_CSp=Waves_CSp)
290 else
291 ! In this case, the segment starts at a time read from the MOM restart file
292 ! or is left at Start_time by MOM_initialize.
2931 Time = Start_time
294 call initialize_MOM(Time, Start_time, param_file, dirs, MOM_CSp, &
295 offline_tracer_mode=offline_tracer_mode, diag_ptr=diag, &
2961 tracer_flow_CSp=tracer_flow_CSp, ice_shelf_CSp=ice_shelf_CSp, waves_CSp=Waves_CSp)
297 endif
298
2991 call get_MOM_state_elements(MOM_CSp, G=grid, GV=GV, US=US, C_p_scaled=fluxes%C_p)
3001 Master_Time = Time
3011 use_ice_shelf = associated(ice_shelf_CSp)
302
3031 if (use_ice_shelf) then
304 ! These arrays are not initialized in most solo cases, but are needed
305 ! when using an ice shelf
3060 call initialize_ice_shelf_fluxes(ice_shelf_CSp, grid, US, fluxes)
3070 call initialize_ice_shelf_forces(ice_shelf_CSp, grid, US, forces)
3080 call ice_shelf_query(ice_shelf_CSp, grid, data_override_shelf_fluxes=override_shelf_fluxes)
3090 if (override_shelf_fluxes) call data_override_init(Ocean_Domain_in=grid%domain%mpp_domain)
310 call get_param(param_file, mod_name, "INITIALIZE_ICE_SHEET_SMB", &
3110 initialize_smb, "Read in a constant SMB for the ice sheet", default=.false.)
3120 if (initialize_smb) call initialize_ice_SMB(fluxes%shelf_sfc_mass_flux, grid, US, param_file)
313 endif
314
315
3161 call callTree_waypoint("done initialize_MOM")
317
3181 call extract_surface_state(MOM_CSp, sfc_state)
319 ! needed to feed adjust_ice_sheet_frazil, set_forcing, shelf_calc_flux
320 !$omp target update if(allocated(sfc_state%Hml)) from(sfc_state%Hml)
321 !$omp target update if(allocated(sfc_state%u)) from(sfc_state%u)
322 !$omp target update if(allocated(sfc_state%v)) from(sfc_state%v)
323 !$omp target update if(allocated(sfc_state%SSS)) from(sfc_state%SSS)
324 !$omp target update if(allocated(sfc_state%SST)) from(sfc_state%SST)
325 !$omp target update if(allocated(sfc_state%sfc_density)) from(sfc_state%sfc_density)
326 !$omp target update if(allocated(sfc_state%frazil)) from(sfc_state%frazil)
327 !$omp target update if(allocated(sfc_state%ocean_mass)) from(sfc_state%ocean_mass)
328 !$omp target update if(allocated(sfc_state%taux_shelf)) from(sfc_state%taux_shelf)
329 !$omp target update if(allocated(sfc_state%tauy_shelf)) from(sfc_state%tauy_shelf)
330 !$omp target update if(allocated(sfc_state%fco2)) from(sfc_state%fco2)
331
3321 if (use_ice_shelf .and. allocated(sfc_state%frazil)) &
3330 call adjust_ice_sheet_frazil(sfc_state, fluxes, Ice_shelf_CSp)
334
335 call surface_forcing_init(Time, grid, US, param_file, diag, &
3361 surface_forcing_CSp, tracer_flow_CSp)
3371 call callTree_waypoint("done surface_forcing_init")
338
339
340 call get_param(param_file, mod_name, "USE_WAVES", Use_Waves, &
3411 "If true, enables surface wave modules.",default=.false.)
342 ! MOM_wave_interface_init is called regardless of the value of USE_WAVES because
343 ! it also initializes statistical waves.
3441 call MOM_wave_interface_init(Time, grid, GV, US, param_file, Waves_CSp, diag)
345
3461 segment_start_time = Time
3471 elapsed_time = 0.0
348
349 ! Read all relevant parameters and write them to the model log.
3501 call log_version(param_file, mod_name, version, "")
351 call get_param(param_file, mod_name, "DT", dt, &
3521 units="s", scale=US%s_to_T, fail_if_missing=.true.)
353 call get_param(param_file, mod_name, "DT_FORCING", dt_forcing, &
354 "The time step for changing forcing, coupling with other "//&
355 "components, or potentially writing certain diagnostics. "//&
356 "The default value is given by DT.", &
3571 units="s", default=US%T_to_s*dt, scale=US%s_to_T)
3581 if (offline_tracer_mode) then
359 call get_param(param_file, mod_name, "DT_OFFLINE", dt_forcing, &
360 "Length of time between reading in of input fields", &
3610 units="s", scale=US%s_to_T, fail_if_missing=.true.)
3620 dt = dt_forcing
363 endif
3641 ntstep = MAX(1,ceiling(dt_forcing/dt - 0.001))
365
3661 Time_step_ocean = real_to_time(dt_forcing, unscale=US%T_to_s)
3671 elapsed_time_master = (abs(dt_forcing - time_to_real(Time_step_ocean, scale=US%s_to_T)) > 1.0e-12*dt_forcing)
3681 if (elapsed_time_master) &
3690 call MOM_mesg("Using real elapsed time for the master clock.", 2)
370
371 ! Determine the segment end time, either from the namelist file or parsed input file.
372 ! Note that Time_unit always is in [s].
373 call get_param(param_file, mod_name, "TIMEUNIT", Time_unit, &
374 "The time unit for DAYMAX, ENERGYSAVEDAYS, and RESTINT.", &
3751 units="s", default=86400.0)
3761 if (years+months+days+hours+minutes+seconds > 0) then
3770 Time_end = increment_date(Time, years, months, days, hours, minutes, seconds)
3780 call MOM_mesg('Segment run length determined from ocean_solo_nml.', 2)
379 call get_param(param_file, mod_name, "DAYMAX", daymax, timeunit=Time_unit, &
3800 default=Time_end, do_not_log=.true.)
381 call log_param(param_file, mod_name, "DAYMAX", daymax, &
382 "The final time of the whole simulation, in units of "//&
383 "TIMEUNIT seconds. This also sets the potential end "//&
384 "time of the present run segment if the end time is "//&
385 "not set via ocean_solo_nml in input.nml.", &
3860 timeunit=Time_unit)
387 else
388 call get_param(param_file, mod_name, "DAYMAX", daymax, &
389 "The final time of the whole simulation, in units of "//&
390 "TIMEUNIT seconds. This also sets the potential end "//&
391 "time of the present run segment if the end time is "//&
392 "not set via ocean_solo_nml in input.nml.", &
3931 timeunit=Time_unit, fail_if_missing=.true.)
3941 Time_end = daymax
395 endif
396
3971 call diag_manager_set_time_end_infra(Time_end)
398
399 call get_param(param_file, mod_name, "SINGLE_STEPPING_CALL", single_step_call, &
400 "If true, advance the state of MOM with a single step "//&
401 "including both dynamics and thermodynamics. If false "//&
4021 "the two phases are advanced with separate calls.", default=.true.)
403 call get_param(param_file, mod_name, "DT_THERM", dt_therm, &
404 "The thermodynamic and tracer advection time step. "//&
405 "Ideally DT_THERM should be an integer multiple of DT "//&
406 "and less than the forcing or coupling time-step, unless "//&
407 "THERMO_SPANS_COUPLING is true, in which case DT_THERM "//&
408 "can be an integer multiple of the coupling timestep. By "//&
409 "default DT_THERM is set to DT.", &
4101 units="s", default=US%T_to_s*dt, scale=US%s_to_T)
411 call get_param(param_file, mod_name, "DIABATIC_FIRST", diabatic_first, &
412 "If true, apply diabatic and thermodynamic processes, "//&
413 "including buoyancy forcing and mass gain or loss, "//&
4141 "before stepping the dynamics forward.", default=.false.)
415
416
4171 if (Time >= Time_end) call MOM_error(FATAL, &
4180 "MOM_driver: The run has been started at or after the end time of the run.")
419
420 call get_param(param_file, mod_name, "RESTART_CONTROL", Restart_control, &
421 "An integer whose bits encode which restart files are "//&
422 "written. Add 2 (bit 1) for a time-stamped file, and odd "//&
423 "(bit 0) for a non-time-stamped file. A non-time-stamped "//&
424 "restart file is saved at the end of the run segment "//&
4251 "for any non-negative value.", default=1)
426 call get_param(param_file, mod_name, "RESTINT", restint, &
427 "The interval between saves of the restart file in units "//&
428 "of TIMEUNIT. Use 0 (the default) to not save "//&
429 "incremental restart files at all.", default=real_to_time(0.0), &
4301 timeunit=Time_unit)
431 call get_param(param_file, mod_name, "WRITE_CPU_STEPS", cpu_steps, &
432 "The number of coupled timesteps between writing the cpu "//&
433 "time. If this is not positive, do not check cpu time, and "//&
434 "the segment run-length can not be set via an elapsed CPU time.", &
4351 default=1000)
436 call get_param(param_file, "MOM", "DEBUG", debug, &
437 "If true, write out verbose debugging data.", &
4381 default=.false., debuggingParam=.true.)
439
4401 call log_param(param_file, mod_name, "ELAPSED TIME AS MASTER", elapsed_time_master)
441
4421 if (cpu_steps > 0) &
443 call MOM_write_cputime_init(param_file, dirs%output_directory, Start_time, &
4441 write_CPU_CSp)
445
446 ! Close the param_file. No further parsing of input is possible after this.
4471 call close_param_file(param_file)
4481 call diag_mediator_close_registration(diag)
449
450 ! Write out a time stamp file.
4511 if (is_root_pe() .and. (calendar_type /= NO_CALENDAR)) call write_time_stamp_file(Time)
452
4531 if (cpu_steps > 0) call write_cputime(Time, 0, write_CPU_CSp)
454
455 if (((.not.BTEST(Restart_control,1)) .and. (.not.BTEST(Restart_control,0))) &
4561 .or. (Restart_control < 0)) permit_incr_restart = .false.
457
4581 if (restint > real_to_time(0.0)) then
459 ! restart_time is the next integral multiple of restint.
460 restart_time = Start_time + restint * &
4610 (1 + ((Time + Time_step_ocean) - Start_time) / restint)
462 else
463 ! Set the time so late that there is no intermediate restart.
4641 restart_time = Time_end + Time_step_ocean
4651 permit_incr_restart = .false.
466 endif
467
4681 call cpu_clock_end(initClock) !end initialization
469
4701 call cpu_clock_begin(mainClock) !begin main loop
471
4721 ns = 1
47313 do while ((ns < nmax) .and. (Time < Time_end))
47412 call callTree_enter("Main loop, MOM_driver.F90",ns)
475
476 ! Set the forcing for the next steps.
47712 if (.not. offline_tracer_mode) then
478 call set_forcing(sfc_state, forces, fluxes, Time, Time_step_ocean, grid, US, &
47912 surface_forcing_CSp)
480 endif
48112 if (debug) then
4820 call MOM_mech_forcing_chksum("After set forcing", forces, grid, US, haloshift=0)
4830 call MOM_forcing_chksum("After set forcing", fluxes, grid, US, haloshift=0)
484 endif
485
48612 if (use_ice_shelf) then
4870 call shelf_calc_flux(sfc_state, fluxes, Time, dt_forcing, ice_shelf_CSp)
4880 call add_shelf_forces(grid, US, Ice_shelf_CSp, forces, external_call=.true.)
489 endif
49012 fluxes%fluxes_used = .false.
49112 fluxes%dt_buoy_accum = dt_forcing
492
49312 if (use_waves) then
4940 call Update_Surface_Waves(grid, GV, US, time, time_step_ocean, waves_csp)
495 endif
496
49712 if (ns==1) then
4981 call finish_MOM_initialization(Time, dirs, MOM_CSp)
499 endif
500
501 ! This call steps the model over a time dt_forcing.
50212 Time1 = Master_Time ; Time = Master_Time
50312 if (offline_tracer_mode) then
5040 call step_offline(forces, fluxes, sfc_state, Time1, dt_forcing, MOM_CSp)
50512 elseif (single_step_call) then
50612 call step_MOM(forces, fluxes, sfc_state, Time1, dt_forcing, MOM_CSp, Waves=Waves_CSP)
507 else
5080 n_max = 1 ; if (dt_forcing > dt) n_max = ceiling(dt_forcing/dt - 0.001)
5090 dt_dyn = dt_forcing / real(n_max)
510
5110 nts = MAX(1,MIN(n_max,floor(dt_therm/dt_dyn + 0.001)))
5120 n_last_thermo = 0
513
5140 Time2 = Time1 ; t_elapsed_seg = 0.0
5150 do n=1,n_max
5160 if (diabatic_first) then
5170 if (modulo(n-1,nts)==0) then
5180 dtdia = dt_dyn*min(ntstep,n_max-(n-1))
519 call step_MOM(forces, fluxes, sfc_state, Time2, dtdia, MOM_CSp, &
520 do_dynamics=.false., do_thermodynamics=.true., &
5210 start_cycle=(n==1), end_cycle=.false., cycle_length=dt_forcing)
522 endif
523
524 call step_MOM(forces, fluxes, sfc_state, Time2, dt_dyn, MOM_CSp, &
525 do_dynamics=.true., do_thermodynamics=.false., &
5260 start_cycle=.false., end_cycle=(n==n_max), cycle_length=dt_forcing)
527 else
528 call step_MOM(forces, fluxes, sfc_state, Time2, dt_dyn, MOM_CSp, &
529 do_dynamics=.true., do_thermodynamics=.false., &
5300 start_cycle=(n==1), end_cycle=.false., cycle_length=dt_forcing)
531
5320 if ((modulo(n,nts)==0) .or. (n==n_max)) then
5330 dtdia = dt_dyn*(n - n_last_thermo)
534 ! Back up Time2 to the start of the thermodynamic segment.
5350 if (n > n_last_thermo+1) &
5360 Time2 = Time2 - real_to_time((dtdia - dt_dyn), unscale=US%T_to_s)
537 call step_MOM(forces, fluxes, sfc_state, Time2, dtdia, MOM_CSp, &
538 do_dynamics=.false., do_thermodynamics=.true., &
5390 start_cycle=.false., end_cycle=(n==n_max), cycle_length=dt_forcing)
5400 n_last_thermo = n
541 endif
542 endif
543
5440 t_elapsed_seg = t_elapsed_seg + dt_dyn
5450 Time2 = Time1 + real_to_time(t_elapsed_seg, unscale=US%T_to_s)
546 enddo
547 endif
548
549! Time = Time + Time_step_ocean
550! This is here to enable fractional-second time steps.
55112 elapsed_time = elapsed_time + dt_forcing
55212 if (elapsed_time > 2.0e9*US%s_to_T) then
553 ! This is here to ensure that the conversion from a real to an integer can be accurately
554 ! represented in long runs (longer than ~63 years). It will also ensure that elapsed time
555 ! does not lose resolution of order the timetype's resolution, provided that the timestep and
556 ! tick are larger than 10-5 seconds. If a clock with a finer resolution is used, a smaller
557 ! value would be required.
5580 time_chg = real_to_time(elapsed_time, unscale=US%T_to_s)
5590 segment_start_time = segment_start_time + time_chg
5600 elapsed_time = elapsed_time - time_to_real(time_chg, scale=US%s_to_T)
561 endif
56212 if (elapsed_time_master) then
5630 Master_Time = segment_start_time + real_to_time(elapsed_time, unscale=US%T_to_s)
564 else
56512 Master_Time = Master_Time + Time_step_ocean
566 endif
56712 Time = Master_Time
568
56912 if (cpu_steps > 0) then ; if (MOD(ns, cpu_steps) == 0) then
5700 call write_cputime(Time, ns+ntstep-1, write_CPU_CSp, nmax)
571 endif ; endif
572
57312 call mech_forcing_diags(forces, dt_forcing, grid, Time, diag, surface_forcing_CSp%handles)
574
57512 if (.not. offline_tracer_mode) then
57612 if (fluxes%fluxes_used) then
577 call forcing_diagnostics(fluxes, sfc_state, grid, US, Time, &
57812 diag, surface_forcing_CSp%handles)
579 else
580 call MOM_error(FATAL, "The solo MOM_driver is not yet set up to handle "//&
5810 "thermodynamic time steps that are longer than the coupling timestep.")
582 endif
583 endif
584
585! See if it is time to write out a restart file - timestamped or not.
58612 if ((permit_incr_restart) .and. (fluxes%fluxes_used) .and. &
587 (Time + (Time_step_ocean/2) > restart_time)) then
5880 if (BTEST(Restart_control,1)) then
589 call save_MOM_restart(MOM_CSp, dirs%restart_output_dir, Time, grid, &
5900 time_stamped=.true., GV=GV)
591 call forcing_save_restart(surface_forcing_CSp, grid, Time, &
5920 dirs%restart_output_dir, .true.)
5930 if (use_ice_shelf) call ice_shelf_save_restart(ice_shelf_CSp, Time, &
5940 dirs%restart_output_dir, .true.)
595 endif
5960 if (BTEST(Restart_control,0)) then
5970 call save_MOM_restart(MOM_CSp, dirs%restart_output_dir, Time, grid, GV=GV)
598 call forcing_save_restart(surface_forcing_CSp, grid, Time, &
5990 dirs%restart_output_dir)
6000 if (use_ice_shelf) call ice_shelf_save_restart(ice_shelf_CSp, Time, &
6010 dirs%restart_output_dir)
602 endif
6030 restart_time = restart_time + restint
604 endif
605
60612 ns = ns + ntstep
60712 call callTree_leave("Main loop")
608 enddo
609
6101 call cpu_clock_end(mainClock)
6111 call cpu_clock_begin(termClock)
6121 if (Restart_control>=0) then
6131 if (.not.MOM_state_is_synchronized(MOM_CSp)) &
614 call MOM_error(WARNING, "End of MOM_main reached with inconsistent "//&
615 "dynamics and advective times. Additional restart fields "//&
6160 "that have not been coded yet would be required for reproducibility.")
6171 if (.not.fluxes%fluxes_used .and. .not.offline_tracer_mode) call MOM_error(FATAL, &
618 "End of MOM_main reached with unused buoyancy fluxes. "//&
619 "For conservation, the ocean restart files can only be "//&
6200 "created after the buoyancy forcing is applied.")
621
6221 call save_MOM_restart(MOM_CSp, dirs%restart_output_dir, Time, grid, GV=GV)
6231 if (use_ice_shelf) call ice_shelf_save_restart(ice_shelf_CSp, Time, &
6240 dirs%restart_output_dir)
625
626 ! Write the ocean solo restart file.
627 call write_ocean_solo_res(Time, Start_time, calendar_type, &
6281 trim(dirs%restart_output_dir)//'ocean_solo.res')
629 endif
630
6311 if (is_root_pe()) then
6321 call open_ASCII_file(unit, "exitcode")
6331 if (Time < daymax) then
6340 write(unit,*) 9
635 else
6361 write(unit,*) 0
637 endif
6381 call close_file(unit)
639 endif
640
6411 call callTree_waypoint("End MOM_main")
6421 if (use_ice_shelf) call ice_shelf_end(ice_shelf_CSp)
6431 call diag_mediator_end(Time, diag, end_diag_manager=.true.)
6441 if (cpu_steps > 0) call write_cputime(Time, ns-1, write_CPU_CSp, call_end=.true.)
6451 call cpu_clock_end(termClock)
646
6471 call MOM_end(MOM_CSp)
648 !$omp target exit data map(delete: MOM_CSp)
649
650 ! This closes out the infrastructure, including clocks, I/O and message passing communicators.
6511 call io_infra_end() ; call MOM_infra_end()
652
653contains
654
655!> Write out the ocean solo restart file to the indicated path.
6563subroutine write_ocean_solo_res(Time, Start_time, calendar, file_path)
657 type(time_type), intent(in) :: Time !< The current model time.
658 type(time_type), intent(in) :: Start_Time !< The start time of the simulation.
659 integer, intent(in) :: calendar !< A coded integer indicating the calendar type.
660 character(len=*), intent(in) :: file_path !< The full path and name of the restart file
661
662 ! Local variables
663 integer :: unit
664 integer :: yr, mon, day, hr, mins, sec ! Temp variables for writing the date.
665
6661 if (.not.is_root_pe()) return
667
6681 call open_ASCII_file(unit, trim(file_path))
6691 write(unit, '(i6,8x,a)') calendar, &
6702 '(Calendar: no_calendar=0, thirty_day_months=1, julian=2, gregorian=3, noleap=4)'
671
6721 call get_date(Start_time, yr, mon, day, hr, mins, sec)
6731 write(unit, '(6i6,8x,a)') yr, mon, day, hr, mins, sec, &
6742 'Model start time: year, month, day, hour, minute, second'
6751 call get_date(Time, yr, mon, day, hr, mins, sec)
6761 write(unit, '(6i6,8x,a)') yr, mon, day, hr, mins, sec, &
6772 'Current model time: year, month, day, hour, minute, second'
6781 call close_file(unit)
6791end subroutine write_ocean_solo_res
680
681
682!> Write out an ascii time stamp file with the model time, following FMS conventions.
6833subroutine write_time_stamp_file(Time)
684 type(time_type), intent(in) :: Time !< The current model time.
685 ! Local variables
686 integer :: unit
687 integer :: yr, mon, day, hr, mins, sec ! Temp variables for writing the date.
688 character(len=9) :: month ! The name of the month
689
6901 if (.not.is_root_PE()) return
691
6921 call open_ASCII_file(unit, 'time_stamp.out', action=APPEND_FILE)
6931 call get_date(Time, yr, mon, day, hr, mins, sec)
6941 month = month_name(mon)
6951 write(unit,'(6i4,2x,a3)') yr, mon, day, hr, mins, sec, month(1:3)
6961 call get_date(Time_end, yr, mon, day, hr, mins, sec)
6971 month = month_name(mon)
6981 write(unit,'(6i4,2x,a3)') yr, mon, day, hr, mins, sec, month(1:3)
6991 call close_file(unit)
700end subroutine write_time_stamp_file
701
702!> Initialize the ensemble manager. If there are no settings for ensemble_size
703!! in input.nml(ensemble.nml), these should not do anything. In coupled
704!! configurations, this all occurs in the external driver.
7051subroutine initialize_ocean_only_ensembles()
7061 integer, dimension(:), allocatable :: ocean_PElist
707 integer, dimension(0) :: atm_PElist, land_PElist, ice_PElist
708 integer :: ensemble_size, nPEs_per, ensemble_info(6)
709
7101 call ensemble_manager_init() ; ensemble_info(:) = get_ensemble_size()
7111 ensemble_size = ensemble_info(1) ; nPEs_per = ensemble_info(2)
7121 if (ensemble_size > 1) then ! There are multiple ensemble members.
7130 allocate(ocean_pelist(nPEs_per))
714 call ensemble_pelist_setup(.true., 0, nPEs_per, 0, 0, atm_pelist, ocean_pelist, &
7150 land_pelist, ice_pelist)
7160 call Set_PElist(ocean_pelist)
7170 deallocate(ocean_pelist)
718 endif
7191end subroutine initialize_ocean_only_ensembles
720
721end program MOM6