update_ocean_model uses the forcing in Ice_ocean_boundary to advance the ocean model's state from the input value of Ocean_state (which must be for time time_start_update) for a time interval of Ocean_coupling_time_step, returning the publicly visible ocean surface properties in Ocean_sfc and storing the new ocean properties in Ocean_state.
424 type(ice_ocean_boundary_type), &
425 intent(in) :: ice_ocean_boundary
427 type(ocean_state_type), &
430 type(ocean_public_type), &
431 intent(inout) :: ocean_sfc
434 type(time_type),
intent(in) :: time_start_update
435 type(time_type),
intent(in) :: ocean_coupling_time_step
437 logical,
optional,
intent(in) :: update_dyn
439 logical,
optional,
intent(in) :: update_thermo
441 logical,
optional,
intent(in) :: ocn_fluxes_used
444 logical,
optional,
intent(in) :: start_cycle
447 logical,
optional,
intent(in) :: end_cycle
450 real,
optional,
intent(in) :: cycle_length
453 type(time_type) :: time_seg_start
456 type(time_type) :: time_thermo_start
459 type(time_type) :: time1
460 integer :: index_bnds(4)
466 real :: t_elapsed_seg
470 integer :: n_last_thermo
471 logical :: thermo_does_span_coupling
474 logical :: step_thermo
475 integer :: is, ie, js, je
477 call calltree_enter(
"update_ocean_model(), ocean_model_MOM.F90")
478 dt_coupling = time_type_to_real(ocean_coupling_time_step)
480 if (.not.
associated(os))
then 481 call mom_error(fatal,
"update_ocean_model called with an unassociated "// &
482 "ocean_state_type structure. ocean_model_init must be "// &
483 "called first to allocate this structure.")
487 do_dyn = .true. ;
if (
present(update_dyn)) do_dyn = update_dyn
488 do_thermo = .true. ;
if (
present(update_thermo)) do_thermo = update_thermo
490 if (do_thermo .and. (time_start_update /= os%Time)) &
491 call mom_error(warning,
"update_ocean_model: internal clock does not "//&
492 "agree with time_start_update argument.")
493 if (do_dyn .and. (time_start_update /= os%Time_dyn)) &
494 call mom_error(warning,
"update_ocean_model: internal dynamics clock does not "//&
495 "agree with time_start_update argument.")
497 if (.not.(do_dyn .or. do_thermo))
call mom_error(fatal, &
498 "update_ocean_model called without updating either dynamics or thermodynamics.")
499 if (do_dyn .and. do_thermo .and. (os%Time /= os%Time_dyn))
call mom_error(fatal, &
500 "update_ocean_model called to update both dynamics and thermodynamics with inconsistent clocks.")
504 is = os%grid%isc ; ie = os%grid%iec ; js = os%grid%jsc ; je = os%grid%jec
505 call coupler_type_spawn(ocean_sfc%fields, os%sfc_state%tr_fields, &
506 (/is,is,ie,ie/), (/js,js,je,je/), as_needed=.true.)
509 call mpp_get_compute_domain(ocean_sfc%Domain, index_bnds(1), index_bnds(2), &
510 index_bnds(3), index_bnds(4))
513 call convert_iob_to_forces(ice_ocean_boundary, os%forces, index_bnds, os%Time_dyn, os%grid, os%US, &
514 os%forcing_CSp, dt_forcing=dt_coupling, reset_avg=os%fluxes%fluxes_used)
515 if (os%use_ice_shelf) &
516 call add_shelf_forces(os%grid, os%US, os%Ice_shelf_CSp, os%forces)
517 if (os%icebergs_alter_ocean) &
518 call iceberg_forces(os%grid, os%forces, os%use_ice_shelf, &
519 os%sfc_state, dt_coupling, os%marine_ice_CSp)
523 if (os%fluxes%fluxes_used)
then 524 call convert_iob_to_fluxes(ice_ocean_boundary, os%fluxes, index_bnds, os%Time, dt_coupling, &
525 os%grid, os%US, os%forcing_CSp, os%sfc_state)
528 if (os%use_ice_shelf) &
529 call shelf_calc_flux(os%sfc_state, os%fluxes, os%Time, dt_coupling, os%Ice_shelf_CSp)
530 if (os%icebergs_alter_ocean) &
531 call iceberg_fluxes(os%grid, os%US, os%fluxes, os%use_ice_shelf, &
532 os%sfc_state, dt_coupling, os%marine_ice_CSp)
534 #ifdef _USE_GENERIC_TRACER 535 call enable_averaging(dt_coupling, os%Time + ocean_coupling_time_step, os%diag)
536 call mom_generic_tracer_fluxes_accumulate(os%fluxes, 1.0)
537 call disable_averaging(os%diag)
542 os%flux_tmp%C_p = os%fluxes%C_p
543 call convert_iob_to_fluxes(ice_ocean_boundary, os%flux_tmp, index_bnds, os%Time, dt_coupling, &
544 os%grid, os%US, os%forcing_CSp, os%sfc_state)
546 if (os%use_ice_shelf) &
547 call shelf_calc_flux(os%sfc_state, os%flux_tmp, os%Time, dt_coupling, os%Ice_shelf_CSp)
548 if (os%icebergs_alter_ocean) &
549 call iceberg_fluxes(os%grid, os%US, os%flux_tmp, os%use_ice_shelf, &
550 os%sfc_state, dt_coupling, os%marine_ice_CSp)
552 call fluxes_accumulate(os%flux_tmp, os%fluxes, os%grid, weight)
553 #ifdef _USE_GENERIC_TRACER 555 call mom_generic_tracer_fluxes_accumulate(os%flux_tmp, weight)
561 if (do_dyn .and.
associated(os%forces%net_mass_src) .and. .not.os%forces%net_mass_src_set) &
562 call get_net_mass_forcing(os%fluxes, os%grid, os%US, os%forces%net_mass_src)
564 if (os%use_waves .and. do_thermo)
then 568 call update_surface_waves(os%grid, os%GV, os%US, os%time, ocean_coupling_time_step, os%waves)
571 if ((os%nstep==0) .and. (os%nstep_thermo==0))
then 572 call finish_mom_initialization(os%Time, os%dirs, os%MOM_CSp, os%restart_CSp)
575 time_thermo_start = os%Time
576 time_seg_start = os%Time ;
if (do_dyn) time_seg_start = os%Time_dyn
577 time1 = time_seg_start
579 if (os%offline_tracer_mode .and. do_thermo)
then 580 call step_offline(os%forces, os%fluxes, os%sfc_state, time1, dt_coupling, os%MOM_CSp)
581 elseif ((.not.do_thermo) .or. (.not.do_dyn))
then 583 call step_mom(os%forces, os%fluxes, os%sfc_state, time1, dt_coupling, os%MOM_CSp, &
584 waves=os%Waves, do_dynamics=do_dyn, do_thermodynamics=do_thermo, &
585 start_cycle=start_cycle, end_cycle=end_cycle, cycle_length=cycle_length, &
586 reset_therm=ocn_fluxes_used)
587 elseif (os%single_step_call)
then 588 call step_mom(os%forces, os%fluxes, os%sfc_state, time1, dt_coupling, os%MOM_CSp, waves=os%Waves)
590 n_max = 1 ;
if (dt_coupling > os%dt) n_max = ceiling(dt_coupling/os%dt - 0.001)
591 dt_dyn = dt_coupling /
real(n_max)
592 thermo_does_span_coupling = (os%thermo_spans_coupling .and. (os%dt_therm > 1.5*dt_coupling))
594 if (thermo_does_span_coupling)
then 595 dt_therm = dt_coupling * floor(os%dt_therm / dt_coupling + 0.001)
596 nts = floor(dt_therm/dt_dyn + 0.001)
598 nts = max(1,min(n_max,floor(os%dt_therm/dt_dyn + 0.001)))
602 time1 = time_seg_start ; t_elapsed_seg = 0.0
604 if (os%diabatic_first)
then 605 if (thermo_does_span_coupling)
call mom_error(fatal, &
606 "MOM is not yet set up to have restarts that work with "//&
607 "THERMO_SPANS_COUPLING and DIABATIC_FIRST.")
608 if (modulo(n-1,nts)==0)
then 609 dtdia = dt_dyn*min(nts,n_max-(n-1))
610 call step_mom(os%forces, os%fluxes, os%sfc_state, time1, dtdia, os%MOM_CSp, &
611 waves=os%Waves, do_dynamics=.false., do_thermodynamics=.true., &
612 start_cycle=(n==1), end_cycle=.false., cycle_length=dt_coupling)
615 call step_mom(os%forces, os%fluxes, os%sfc_state, time1, dt_dyn, os%MOM_CSp, &
616 waves=os%Waves, do_dynamics=.true., do_thermodynamics=.false., &
617 start_cycle=.false., end_cycle=(n==n_max), cycle_length=dt_coupling)
619 call step_mom(os%forces, os%fluxes, os%sfc_state, time1, dt_dyn, os%MOM_CSp, &
620 waves=os%Waves, do_dynamics=.true., do_thermodynamics=.false., &
621 start_cycle=(n==1), end_cycle=.false., cycle_length=dt_coupling)
623 step_thermo = .false.
624 if (thermo_does_span_coupling)
then 626 step_thermo = mom_state_is_synchronized(os%MOM_CSp, adv_dyn=.true.)
627 elseif ((modulo(n,nts)==0) .or. (n==n_max))
then 628 dtdia = dt_dyn*(n - n_last_thermo)
633 if (step_thermo)
then 635 time1 = time1 - real_to_time(dtdia - dt_dyn)
636 call step_mom(os%forces, os%fluxes, os%sfc_state, time1, dtdia, os%MOM_CSp, &
637 waves=os%Waves, do_dynamics=.false., do_thermodynamics=.true., &
638 start_cycle=.false., end_cycle=(n==n_max), cycle_length=dt_coupling)
642 t_elapsed_seg = t_elapsed_seg + dt_dyn
643 time1 = time_seg_start + real_to_time(t_elapsed_seg)
647 if (do_dyn) os%Time_dyn = time_seg_start + ocean_coupling_time_step
648 if (do_dyn) os%nstep = os%nstep + 1
649 os%Time = time_thermo_start
650 if (do_thermo) os%Time = os%Time + ocean_coupling_time_step
651 if (do_thermo) os%nstep_thermo = os%nstep_thermo + 1
654 call mech_forcing_diags(os%forces, dt_coupling, os%grid, os%Time_dyn, os%diag, os%forcing_CSp%handles)
657 if (os%fluxes%fluxes_used .and. do_thermo)
then 658 call forcing_diagnostics(os%fluxes, os%sfc_state, os%grid, os%US, os%Time, os%diag, os%forcing_CSp%handles)
664 call convert_state_to_ocean_type(os%sfc_state, ocean_sfc, os%grid, os%US)
665 time1 = os%Time ;
if (do_dyn) time1 = os%Time_dyn
666 call coupler_type_send_data(ocean_sfc%fields, time1)
668 call calltree_leave(
"update_ocean_model()")