44 use mom_cpu_clock, only : cpu_clock_id, cpu_clock_begin, cpu_clock_end
51 use mom_domains, only : mom_infra_init, mom_infra_end
60 use mom_io, only : check_nml_error, io_infra_init, io_infra_end
61 use mom_io, only : append_file, ascii_file, readonly_file, single_file
68 use mom_time_manager, only : time_type, set_date, set_time, get_date, time_type_to_real
69 use mom_time_manager, only :
operator(+),
operator(-),
operator(*),
operator(/)
79 use ensemble_manager_mod
, only : ensemble_manager_init, get_ensemble_size
80 use ensemble_manager_mod
, only : ensemble_pelist_setup
81 use mpp_mod
, only : set_current_pelist => mpp_set_current_pelist
89 #include <MOM_memory.h> 102 logical :: use_ice_shelf
105 logical :: permit_incr_restart = .true.
113 integer :: nmax=2000000000;
119 type(time_type),
target :: Time
122 type(time_type) :: Master_Time
124 type(time_type) :: Time1
126 type(time_type) :: Start_time
127 type(time_type) :: segment_start_time
128 type(time_type) :: Time_end
129 type(time_type) :: write_energy_time
130 type(time_type) :: restart_time
131 type(time_type) :: Time_step_ocean
133 real :: elapsed_time = 0.0
134 logical :: elapsed_time_master
144 integer :: Restart_control
152 type(time_type) :: restint
153 type(time_type) :: daymax
154 type(time_type) :: energysavedays
157 integer :: date_init(6)=0
158 integer :: date(6)=-1
159 integer :: years=0, months=0, days=0
160 integer :: hours=0, minutes=0, seconds=0
161 integer :: yr, mon, day, hr, min, sec
164 character(len=9) :: month
165 character(len=16) :: calendar =
'julian' 166 integer :: calendar_type=-1
168 integer :: unit, io_status, ierr
169 integer :: ensemble_size, nPEs_per, ensemble_info(6)
171 integer,
dimension(0) :: atm_PElist, land_PElist, ice_PElist
172 integer,
dimension(:),
allocatable :: ocean_PElist
173 logical :: unit_in_use
174 integer :: initClock, mainClock, termClock
176 logical :: offline_tracer_mode
191 character(len=4),
parameter :: vers_num =
'v2.0' 193 #include "version_variable.h" 194 character(len=40) :: mod_name =
"MOM_main (MOM_driver)" 196 integer :: ocean_nthreads = 1
197 integer :: ncores_per_node = 36
198 logical :: use_hyper_thread = .false.
199 integer :: omp_get_num_threads,omp_get_thread_num,get_cpu_affinity,adder,base_cpu
200 namelist /ocean_solo_nml/ date_init, calendar, months, days, hours, minutes, seconds,&
201 ocean_nthreads, ncores_per_node, use_hyper_thread
207 call mom_infra_init() ;
call io_infra_init()
212 call ensemble_manager_init() ; ensemble_info(:) = get_ensemble_size()
213 ensemble_size=ensemble_info(1) ; npes_per=ensemble_info(2)
214 if (ensemble_size > 1)
then 215 allocate(ocean_pelist(npes_per))
216 call ensemble_pelist_setup(.true., 0, npes_per, 0, 0, atm_pelist, ocean_pelist, &
217 land_pelist, ice_pelist)
218 call set_current_pelist(ocean_pelist)
219 deallocate(ocean_pelist)
223 initclock = cpu_clock_id(
'Initialization' )
224 mainclock = cpu_clock_id(
'Main loop' )
225 termclock = cpu_clock_id(
'Termination' )
226 call cpu_clock_begin(initclock)
228 call mom_mesg(
'======== Model being driven by MOM_driver ========', 2)
233 call open_file(unit,
'input.nml', form=ascii_file, action=readonly_file)
234 read(unit, ocean_solo_nml, iostat=io_status)
235 call close_file(unit)
236 ierr = check_nml_error(io_status,
'ocean_solo_nml')
237 if (years+months+days+hours+minutes+seconds > 0)
then 238 if (is_root_pe())
write(*,ocean_solo_nml)
260 if (
file_exists(trim(dirs%restart_input_dir)//
'ocean_solo.res'))
then 261 call open_file(unit,trim(dirs%restart_input_dir)//
'ocean_solo.res', &
262 form=ascii_file,action=readonly_file)
263 read(unit,*) calendar_type
264 read(unit,*) date_init
266 call close_file(unit)
269 if (calendar(1:6) ==
'JULIAN')
then ; calendar_type = julian
270 else if (calendar(1:9) ==
'GREGORIAN')
then ; calendar_type = gregorian
271 else if (calendar(1:6) ==
'NOLEAP')
then ; calendar_type = noleap
272 else if (calendar(1:10)==
'THIRTY_DAY')
then ; calendar_type = thirty_day_months
273 else if (calendar(1:11)==
'NO_CALENDAR') then; calendar_type = no_calendar
274 else if (calendar(1:1) /=
' ')
then 275 call mom_error(fatal,
'MOM_driver: Invalid namelist value '//trim(calendar)//
' for calendar')
277 call mom_error(fatal,
'MOM_driver: No namelist value for calendar')
280 call set_calendar_type(calendar_type)
283 if (sum(date_init) > 0)
then 284 start_time = set_date(date_init(1),date_init(2), date_init(3), &
285 date_init(4),date_init(5),date_init(6))
287 start_time = set_time(0,days=0)
290 if (sum(date) >= 0)
then 292 segment_start_time = set_date(date(1),date(2),date(3),date(4),date(5),date(6))
293 time = segment_start_time
295 call initialize_mom(time, param_file, dirs, mom_csp, segment_start_time, offline_tracer_mode = offline_tracer_mode)
300 call initialize_mom(time, param_file, dirs, mom_csp, offline_tracer_mode=offline_tracer_mode)
302 fluxes%C_p = mom_csp%tv%C_p
307 call calculate_surface_state(state, mom_csp%u, mom_csp%v, mom_csp%h, &
308 mom_csp%ave_ssh, grid, gv, mom_csp)
312 surface_forcing_csp, mom_csp%tracer_flow_CSp)
315 call get_param(param_file, mod_name,
"ICE_SHELF", use_ice_shelf, &
316 "If true, enables the ice shelf model.", default=.false.)
317 if (use_ice_shelf)
then 320 call initialize_ice_shelf(param_file, grid, time, ice_shelf_csp, mom_csp%diag, fluxes)
324 mom_csp%ntrunc, start_time, sum_output_csp)
325 call mom_write_cputime_init(param_file, dirs%output_directory, start_time, &
329 segment_start_time = time
333 call log_version(param_file, mod_name, version,
"")
334 call get_param(param_file, mod_name,
"DT", dt, fail_if_missing=.true.)
335 call get_param(param_file, mod_name,
"DT_FORCING", time_step, &
336 "The time step for changing forcing, coupling with other \n"//&
337 "components, or potentially writing certain diagnostics. \n"//&
338 "The default value is given by DT.", units=
"s", default=dt)
339 if (offline_tracer_mode)
then 340 call get_param(param_file, mod_name,
"DT_OFFLINE", time_step, &
341 "Time step for the offline time step")
344 ntstep = max(1,ceiling(time_step/dt - 0.001))
346 time_step_ocean = set_time(int(floor(time_step+0.5)))
347 elapsed_time_master = (abs(time_step - time_type_to_real(time_step_ocean)) > 1.0e-12*time_step)
348 if (elapsed_time_master) &
349 call mom_mesg(
"Using real elapsed time for the master clock.", 2)
352 call get_param(param_file, mod_name,
"TIMEUNIT", time_unit, &
353 "The time unit for DAYMAX, ENERGYSAVEDAYS, and RESTINT.", &
354 units=
"s", default=86400.0)
355 if (years+months+days+hours+minutes+seconds > 0)
then 356 time_end = increment_date(time, years, months, days, hours, minutes, seconds)
357 call mom_mesg(
'Segment run length determined from ocean_solo_nml.', 2)
358 call get_param(param_file, mod_name,
"DAYMAX", daymax, timeunit=time_unit, &
359 default=time_end, do_not_log=.true.)
360 call log_param(param_file, mod_name,
"DAYMAX", daymax, &
361 "The final time of the whole simulation, in units of \n"//&
362 "TIMEUNIT seconds. This also sets the potential end \n"//&
363 "time of the present run segment if the end time is \n"//&
364 "not set via ocean_solo_nml in input.nml.", &
367 call get_param(param_file, mod_name,
"DAYMAX", daymax, &
368 "The final time of the whole simulation, in units of \n"//&
369 "TIMEUNIT seconds. This also sets the potential end \n"//&
370 "time of the present run segment if the end time is \n"//&
371 "not set via ocean_solo_nml in input.nml.", &
372 timeunit=time_unit, fail_if_missing=.true.)
376 if (time >= time_end)
call mom_error(fatal, &
377 "MOM_driver: The run has been started at or after the end time of the run.")
379 call get_param(param_file, mod_name,
"RESTART_CONTROL", restart_control, &
380 "An integer whose bits encode which restart files are \n"//&
381 "written. Add 2 (bit 1) for a time-stamped file, and odd \n"//&
382 "(bit 0) for a non-time-stamped file. A non-time-stamped \n"//&
383 "restart file is saved at the end of the run segment \n"//&
384 "for any non-negative value.", default=1)
385 call get_param(param_file, mod_name,
"RESTINT", restint, &
386 "The interval between saves of the restart file in units \n"//&
387 "of TIMEUNIT. Use 0 (the default) to not save \n"//&
388 "incremental restart files at all.", default=set_time(0), &
390 call get_param(param_file, mod_name,
"ENERGYSAVEDAYS", energysavedays, &
391 "The interval in units of TIMEUNIT between saves of the \n"//&
392 "energies of the run and other globally summed diagnostics.", &
393 default=set_time(int(time_step+0.5)), timeunit=time_unit)
395 call log_param(param_file, mod_name,
"ELAPSED TIME AS MASTER", elapsed_time_master)
402 if (calendar_type /= no_calendar)
then 403 call open_file(unit,
'time_stamp.out', form=ascii_file, action=append_file, &
404 threading=single_file)
405 call get_date(time, date(1), date(2), date(3), date(4), date(5), date(6))
406 month = month_name(date(2))
407 if (is_root_pe())
write(unit,
'(6i4,2x,a3)') date, month(1:3)
408 call get_date(time_end, date(1), date(2), date(3), date(4), date(5), date(6))
409 month = month_name(date(2))
410 if (is_root_pe())
write(unit,
'(6i4,2x,a3)') date, month(1:3)
411 call close_file(unit)
417 call write_cputime(time, 0, nmax, write_cpu_csp)
419 write_energy_time = start_time + energysavedays * &
420 (1 + (time - start_time) / energysavedays)
422 if (((.not.btest(restart_control,1)) .and. (.not.btest(restart_control,0))) &
423 .or. (restart_control < 0)) permit_incr_restart = .false.
425 if (restint > set_time(0))
then 427 restart_time = start_time + restint * &
428 (1 + ((time + time_step_ocean) - start_time) / restint)
431 restart_time = time_end + time_step_ocean
432 permit_incr_restart = .false.
435 call cpu_clock_end(initclock)
437 call cpu_clock_begin(mainclock)
440 do while ((n < nmax) .and. (time < time_end))
444 if (.not. offline_tracer_mode)
then 445 call set_forcing(state, fluxes, time, time_step_ocean, grid, &
448 if (mom_csp%debug)
then 452 if (use_ice_shelf)
then 458 fluxes%fluxes_used = .false.
459 fluxes%dt_buoy_accum = time_step
462 call finish_mom_initialization(time, dirs, mom_csp, fluxes)
464 call write_energy(mom_csp%u, mom_csp%v, mom_csp%h, mom_csp%tv, &
465 time, 0, grid, gv, sum_output_csp, mom_csp%tracer_flow_CSp)
469 time1 = master_time ; time = master_time
470 if (offline_tracer_mode)
then 471 call step_offline(fluxes, state, time1, time_step, mom_csp)
473 call step_mom(fluxes, state, time1, time_step, mom_csp)
478 elapsed_time = elapsed_time + time_step
479 if (elapsed_time > 2e9)
then 486 segment_start_time = segment_start_time + set_time(int(floor(elapsed_time)))
487 elapsed_time = elapsed_time - floor(elapsed_time)
489 if (elapsed_time_master)
then 490 master_time = segment_start_time + set_time(int(floor(elapsed_time+0.5)))
492 master_time = master_time + time_step_ocean
496 call enable_averaging(time_step, time, mom_csp%diag)
498 surface_forcing_csp%handles)
499 call disable_averaging(mom_csp%diag)
501 if (.not. offline_tracer_mode)
then 502 if (fluxes%fluxes_used)
then 503 call enable_averaging(fluxes%dt_buoy_accum, time, mom_csp%diag)
505 mom_csp%diag, surface_forcing_csp%handles)
506 call accumulate_net_input(fluxes, state, fluxes%dt_buoy_accum, grid, sum_output_csp)
507 call disable_averaging(mom_csp%diag)
509 call mom_error(fatal,
"The solo MOM_driver is not yet set up to handle "//&
510 "thermodynamic time steps that are longer than the coupling timestep.")
515 if ((time + (time_step_ocean/2) > write_energy_time) .and. &
516 (mom_csp%t_dyn_rel_adv == 0.0))
then 517 call write_energy(mom_csp%u, mom_csp%v, mom_csp%h, &
518 mom_csp%tv, time, n+ntstep-1, grid, gv, sum_output_csp, &
519 mom_csp%tracer_flow_CSp)
520 call write_cputime(time, n+ntstep-1, nmax, write_cpu_csp)
521 write_energy_time = write_energy_time + energysavedays
525 if ((permit_incr_restart) .and. (fluxes%fluxes_used) .and. &
526 (time + (time_step_ocean/2) > restart_time))
then 527 if (btest(restart_control,1))
then 528 call save_restart(dirs%restart_output_dir, time, grid, &
529 mom_csp%restart_CSp, .true., gv=gv)
530 call forcing_save_restart(surface_forcing_csp, grid, time, &
531 dirs%restart_output_dir, .true.)
533 dirs%restart_output_dir, .true.)
535 if (btest(restart_control,0))
then 536 call save_restart(dirs%restart_output_dir, time, grid, &
537 mom_csp%restart_CSp, gv=gv)
538 call forcing_save_restart(surface_forcing_csp, grid, time, &
539 dirs%restart_output_dir)
541 dirs%restart_output_dir)
543 restart_time = restart_time + restint
550 call cpu_clock_end(mainclock)
551 call cpu_clock_begin(termclock)
552 if (restart_control>=0)
then 553 if (mom_csp%t_dyn_rel_adv > 0.0)
call mom_error(warning,
"End of MOM_main reached "//&
554 "with inconsistent dynamics and advective times. Additional restart fields "//&
555 "that have not been coded yet would be required for reproducibility.")
556 if (.not.fluxes%fluxes_used .and. .not.offline_tracer_mode)
call mom_error(fatal, &
557 "End of MOM_main reached with unused buoyancy fluxes. "//&
558 "For conservation, the ocean restart files can only be "//&
559 "created after the buoyancy forcing is applied.")
561 call save_restart(dirs%restart_output_dir, time, grid, mom_csp%restart_CSp, gv=gv)
563 dirs%restart_output_dir)
565 call open_file(unit, trim(dirs%restart_output_dir)//
'ocean_solo.res', nohdrs=.true.)
566 if (is_root_pe())
then 567 write(unit,
'(i6,8x,a)') calendar_type, &
568 '(Calendar: no_calendar=0, thirty_day_months=1, julian=2, gregorian=3, noleap=4)' 570 call get_date(start_time, yr, mon, day, hr, min, sec)
571 write(unit,
'(6i6,8x,a)') yr, mon, day, hr, min, sec, &
572 'Model start time: year, month, day, hour, minute, second' 573 call get_date(time, yr, mon, day, hr, min, sec)
574 write(unit,
'(6i6,8x,a)') yr, mon, day, hr, min, sec, &
575 'Current model time: year, month, day, hour, minute, second' 577 call close_file(unit)
580 if (is_root_pe())
then 582 INQUIRE(unit,opened=unit_in_use)
583 if (.not.unit_in_use)
exit 585 open(unit,file=
"exitcode",form=
"FORMATTED",status=
"REPLACE",action=
"WRITE")
586 if (time < daymax)
then 596 call cpu_clock_end(termclock)
598 call io_infra_end ;
call mom_infra_end
600 call mom_end(mom_csp)
601 if (use_ice_shelf)
call ice_shelf_end(ice_shelf_csp)
subroutine, public set_forcing(state, fluxes, day_start, day_interval, G, CS)
The following structure contains pointers to various fields which may be used describe the surface st...
subroutine, public write_cputime_start_clock(CS)
subroutine, public initialize_mom(Time, param_file, dirs, CS, Time_in, offline_tracer_mode)
This subroutine initializes MOM.
subroutine, public mom_write_cputime_init(param_file, directory, Input_start_time, CS)
This module implements boundary forcing for MOM6.
Ocean grid type. See mom_grid for details.
subroutine, public write_cputime(day, n, nmax, CS)
This is the main routine for MOM.
Provides the ocean grid type.
subroutine, public mom_forcing_chksum(mesg, fluxes, G, haloshift)
Write out chksums for basic state variables.
subroutine, public calltree_leave(mesg)
Writes a message about leaving a subroutine if call tree reporting is active.
This module contains I/O framework code.
subroutine, public ice_shelf_end(CS)
Deallocates all memory associated with this module.
subroutine, public accumulate_net_input(fluxes, state, dt, G, CS)
This subroutine accumates the net input of volume, and perhaps later salt and heat, through the ocean surface for use in diagnosing conservation.
Implements the thermodynamic aspects of ocean / ice-shelf interactions,.
subroutine, public calltree_waypoint(mesg, n)
Writes a message about reaching a milestone if call tree reporting is active.
subroutine, public write_energy(u, v, h, tv, day, n, G, GV, CS, tracer_CSp)
This subroutine calculates and writes the total model energy, the energy and mass of each layer...
character(len=len(input_string)) function, public uppercase(input_string)
subroutine, public close_param_file(CS, quiet_close, component)
subroutine, public ice_shelf_save_restart(CS, Time, directory, time_stamped, filename_suffix)
Save the ice shelf restart file.
logical function, public is_root_pe()
subroutine, public forcing_diagnostics(fluxes, state, dt, G, diag, handles)
Offer buoyancy forcing fields for diagnostics for those fields registered as part of register_forcing...
subroutine, public forcing_save_restart(CS, G, Time, directory, time_stamped, filename_suffix)
Control structure for this module.
subroutine, public initialize_ice_shelf(param_file, ocn_grid, Time, CS, diag, fluxes, Time_in, solo_ice_sheet_in)
Initializes shelf model data, parameters and diagnostics.
Structure that contains pointers to the boundary forcing used to drive the liquid ocean simulated by ...
subroutine, public mom_mesg(message, verb, all_print)
Control structure that contains ice shelf parameters and diagnostics handles.
subroutine, public calculate_surface_state(state, u, v, h, ssh, G, GV, CS)
This subroutine sets the surface (return) properties of the ocean model by setting the appropriate fi...
subroutine, public step_offline(fluxes, state, Time_start, time_interval, CS)
step_offline is the main driver for running tracers offline in MOM6. This has been primarily develope...
subroutine, public save_restart(directory, time, G, CS, time_stamped, filename, GV)
subroutine, public step_mom(fluxes, state, Time_start, time_interval, CS)
This subroutine orchestrates the time stepping of MOM. The adiabatic dynamics are stepped by calls to...
subroutine, public mom_end(CS)
End of model.
subroutine, public surface_forcing_init(Time, G, param_file, diag, CS, tracer_flow_CSp)
subroutine, public mom_error(level, message, all_print)
subroutine, public mech_forcing_diags(fluxes, dt, G, diag, handles)
Offer mechanical forcing fields for diagnostics for those fields registered as part of register_forci...
subroutine, public finish_mom_initialization(Time, dirs, CS, fluxes)
This subroutine finishes initializing MOM and writes out the initial conditions.
subroutine, public shelf_calc_flux(state, fluxes, Time, time_step, CS)
Calculates fluxes between the ocean and ice-shelf using the three-equations formulation (optional to ...
subroutine, public mom_sum_output_init(G, param_file, directory, ntrnc, Input_start_time, CS)
subroutine, public calltree_enter(mesg, n)
Writes a message about entering a subroutine if call tree reporting is active.