60 use mom_time_manager, only :
operator(+),
operator(-),
operator(*),
operator(/)
68 use mpp_domains_mod
, only : domain2d, mpp_get_layout, mpp_get_global_domain
69 use mpp_domains_mod
, only : mpp_define_domains, mpp_get_compute_domain, mpp_get_data_domain
72 use fms_mod
, only : stdout
73 use mpp_mod
, only : mpp_chksum
75 use mom_eos, only : gsw_sp_from_sr, gsw_pt_from_ct
77 #include <MOM_memory.h> 79 #ifdef _USE_GENERIC_TRACER 80 use mom_generic_tracer, only : mom_generic_flux_init,mom_generic_tracer_fluxes_accumulate
83 implicit none ;
private 87 public ice_ocean_boundary_type
90 public ice_ocn_bnd_type_chksum
103 type(domain2d) :: domain
104 logical :: is_ocean_pe
105 character(len=32) :: instance_name =
'' 108 integer,
pointer,
dimension(:) :: pelist => null()
109 logical,
pointer,
dimension(:,:) :: maskmap =>null()
115 integer :: stagger = -999
124 real,
pointer,
dimension(:,:) :: &
137 integer,
dimension(2) :: axes = 0
146 logical :: is_ocean_pe = .false.
147 type(time_type) :: time
148 integer :: restart_control
154 type(time_type) :: energysavedays
156 type(time_type) :: write_energy_time
159 logical :: use_ice_shelf
160 logical :: icebergs_apply_rigid_boundary
162 real :: berg_area_threshold
165 real :: latent_heat_fusion
166 real :: density_iceberg
168 logical :: restore_salinity
170 logical :: restore_temp
205 type(time_type),
intent(in) :: Time_init
206 type(time_type),
intent(in) :: Time_in
222 #include "version_variable.h" 223 character(len=40) :: mdl =
"ocean_model_init" 224 character(len=48) :: stagger
225 integer :: secs, days
227 logical :: offline_tracer_mode
230 if (
associated(os))
then 231 call mom_error(warning,
"ocean_model_init called with an associated "// &
232 "ocean_state_type structure. Model is already initialized.")
237 os%is_ocean_pe = ocean_sfc%is_ocean_pe
238 if (.not.os%is_ocean_pe)
return 240 os%state%tr_fields => ocean_sfc%fields
242 call initialize_mom(os%Time, param_file, os%dirs, os%MOM_CSp, time_in, &
243 offline_tracer_mode=offline_tracer_mode)
244 os%grid => os%MOM_CSp%G ; os%GV => os%MOM_CSp%GV
245 os%C_p = os%MOM_CSp%tv%C_p
246 os%fluxes%C_p = os%MOM_CSp%tv%C_p
250 call get_param(param_file, mdl,
"RESTART_CONTROL", os%Restart_control, &
251 "An integer whose bits encode which restart files are \n"//&
252 "written. Add 2 (bit 1) for a time-stamped file, and odd \n"//&
253 "(bit 0) for a non-time-stamped file. A restart file \n"//&
254 "will be saved at the end of the run segment for any \n"//&
255 "non-negative value.", default=1)
256 call get_param(param_file, mdl,
"TIMEUNIT", time_unit, &
257 "The time unit for ENERGYSAVEDAYS.", &
258 units=
"s", default=86400.0)
259 call get_param(param_file, mdl,
"ENERGYSAVEDAYS",os%energysavedays, &
260 "The interval in units of TIMEUNIT between saves of the \n"//&
261 "energies of the run and other globally summed diagnostics.", &
262 default=set_time(0,days=1), timeunit=time_unit)
264 call get_param(param_file, mdl,
"OCEAN_SURFACE_STAGGER", stagger, &
265 "A case-insensitive character string to indicate the \n"//&
266 "staggering of the surface velocity field that is \n"//&
267 "returned to the coupler. Valid values include \n"//&
268 "'A', 'B', or 'C'.", default=
"C")
269 if (
uppercase(stagger(1:1)) ==
'A')
then ; ocean_sfc%stagger = agrid
270 elseif (
uppercase(stagger(1:1)) ==
'B')
then ; ocean_sfc%stagger = bgrid_ne
271 elseif (
uppercase(stagger(1:1)) ==
'C')
then ; ocean_sfc%stagger = cgrid_ne
272 else ;
call mom_error(fatal,
"ocean_model_init: OCEAN_SURFACE_STAGGER = "// &
273 trim(stagger)//
" is invalid.") ;
endif 275 call get_param(param_file, mdl,
"RESTORE_SALINITY",os%restore_salinity, &
276 "If true, the coupled driver will add a globally-balanced \n"//&
277 "fresh-water flux that drives sea-surface salinity \n"//&
278 "toward specified values.", default=.false.)
279 call get_param(param_file, mdl,
"RESTORE_TEMPERATURE",os%restore_temp, &
280 "If true, the coupled driver will add a \n"//&
281 "heat flux that drives sea-surface temperauture \n"//&
282 "toward specified values.", default=.false.)
283 call get_param(param_file, mdl,
"RHO_0", rho0, &
284 "The mean ocean density used with BOUSSINESQ true to \n"//&
285 "calculate accelerations and the mass for conservation \n"//&
286 "properties, or with BOUSSINSEQ false to convert some \n"//&
287 "parameters from vertical units of m to kg m-2.", &
288 units=
"kg m-3", default=1035.0)
289 call get_param(param_file, mdl,
"G_EARTH", g_earth, &
290 "The gravitational acceleration of the Earth.", &
291 units=
"m s-2", default = 9.80)
293 call get_param(param_file, mdl,
"ICE_SHELF", os%use_ice_shelf, &
294 "If true, enables the ice shelf model.", default=.false.)
296 call get_param(param_file, mdl,
"ICEBERGS_APPLY_RIGID_BOUNDARY", os%icebergs_apply_rigid_boundary, &
297 "If true, allows icebergs to change boundary condition felt by ocean", default=.false.)
299 if (os%icebergs_apply_rigid_boundary)
then 300 call get_param(param_file, mdl,
"KV_ICEBERG", os%kv_iceberg, &
301 "The viscosity of the icebergs", units=
"m2 s-1",default=1.0e10)
302 call get_param(param_file, mdl,
"DENSITY_ICEBERGS", os%density_iceberg, &
303 "A typical density of icebergs.", units=
"kg m-3", default=917.0)
304 call get_param(param_file, mdl,
"LATENT_HEAT_FUSION", os%latent_heat_fusion, &
305 "The latent heat of fusion.", units=
"J/kg", default=hlf)
306 call get_param(param_file, mdl,
"BERG_AREA_THRESHOLD", os%berg_area_threshold, &
307 "Fraction of grid cell which iceberg must occupy, so that fluxes \n"//&
308 "below berg are set to zero. Not applied for negative \n"//&
309 " values.", units=
"non-dim", default=-1.0)
312 os%press_to_z = 1.0/(rho0*g_earth)
314 call surface_forcing_init(time_in, os%grid, param_file, os%MOM_CSp%diag, &
315 os%forcing_CSp, os%restore_salinity, os%restore_temp)
317 if (os%use_ice_shelf)
then 318 call initialize_ice_shelf(param_file, os%grid, os%Time, os%ice_shelf_CSp, &
319 os%MOM_CSp%diag, os%fluxes)
321 if (os%icebergs_apply_rigid_boundary)
then 324 if (.not. os%use_ice_shelf)
call allocate_forcing_type(os%grid, os%fluxes, ustar=.true., shelf=.true.)
328 os%MOM_CSp%ntrunc, time_init, os%sum_output_CSp)
335 os%write_energy_time = time_init + os%energysavedays * &
336 (1 + (os%Time - time_init) / os%energysavedays)
338 if(
ASSOCIATED(os%grid%Domain%maskmap))
then 340 os%MOM_CSp%diag, maskmap=os%grid%Domain%maskmap)
351 write(*,
'(/12x,a/)')
'======== COMPLETED MOM INITIALIZATION ========' 368 time_start_update, Ocean_coupling_time_step)
369 type(ice_ocean_boundary_type),
intent(inout) :: Ice_ocean_boundary
372 type(time_type),
intent(in) :: time_start_update
373 type(time_type),
intent(in) :: Ocean_coupling_time_step
393 type(time_type) :: Master_time
395 type(time_type) :: Time1
397 integer :: index_bnds(4)
401 integer :: secs, days
404 call get_time(ocean_coupling_time_step, secs, days)
405 time_step = 86400.0*
real(days) +
real(secs)
407 if (time_start_update /= os%Time)
then 408 call mom_error(warning,
"update_ocean_model: internal clock does not "//&
409 "agree with time_start_update argument.")
411 if (.not.
associated(os))
then 412 call mom_error(fatal,
"update_ocean_model called with an unassociated "// &
413 "ocean_state_type structure. ocean_model_init must be "// &
414 "called first to allocate this structure.")
419 call mpp_get_compute_domain(ocean_sfc%Domain, index_bnds(1), index_bnds(2), &
420 index_bnds(3), index_bnds(4))
424 if (os%fluxes%fluxes_used)
then 425 call enable_averaging(time_step, os%Time + ocean_coupling_time_step, os%MOM_CSp%diag)
426 call convert_iob_to_fluxes(ice_ocean_boundary, os%fluxes, index_bnds, os%Time, &
427 os%grid, os%forcing_CSp, os%state, os%restore_salinity,os%restore_temp)
428 #ifdef _USE_GENERIC_TRACER 429 call mom_generic_tracer_fluxes_accumulate(os%fluxes, weight)
433 if (os%use_ice_shelf)
then 434 call shelf_calc_flux(os%State, os%fluxes, os%Time, time_step, os%Ice_shelf_CSp)
436 if (os%icebergs_apply_rigid_boundary)
then 438 call add_berg_flux_to_shelf(os%grid, os%fluxes,os%use_ice_shelf,os%density_iceberg,os%kv_iceberg, os%latent_heat_fusion, os%State, time_step, os%berg_area_threshold)
441 os%fluxes%fluxes_used = .false.
442 os%fluxes%dt_buoy_accum = time_step
444 os%flux_tmp%C_p = os%fluxes%C_p
445 call convert_iob_to_fluxes(ice_ocean_boundary, os%flux_tmp, index_bnds, os%Time, &
446 os%grid, os%forcing_CSp, os%state, os%restore_salinity,os%restore_temp)
447 if (os%use_ice_shelf)
then 448 call shelf_calc_flux(os%State, os%flux_tmp, os%Time, time_step, os%Ice_shelf_CSp)
450 if (os%icebergs_apply_rigid_boundary)
then 452 call add_berg_flux_to_shelf(os%grid, os%flux_tmp, os%use_ice_shelf,os%density_iceberg,os%kv_iceberg, os%latent_heat_fusion, os%State, time_step, os%berg_area_threshold)
455 call forcing_accumulate(os%flux_tmp, os%fluxes, time_step, os%grid, weight)
456 #ifdef _USE_GENERIC_TRACER 457 call mom_generic_tracer_fluxes_accumulate(os%flux_tmp, weight)
461 if (os%nstep==0)
then 462 call finish_mom_initialization(os%Time, os%dirs, os%MOM_CSp, os%fluxes)
464 call write_energy(os%MOM_CSp%u, os%MOM_CSp%v, os%MOM_CSp%h, os%MOM_CSp%tv, &
465 os%Time, 0, os%grid, os%GV, os%sum_output_CSp, &
466 os%MOM_CSp%tracer_flow_CSp)
469 call disable_averaging(os%MOM_CSp%diag)
470 master_time = os%Time ; time1 = os%Time
472 if(os%MOM_Csp%offline_tracer_mode)
then 473 call step_offline(os%fluxes, os%state, time1, time_step, os%MOM_CSp)
475 call step_mom(os%fluxes, os%state, time1, time_step, os%MOM_CSp)
478 os%Time = master_time + ocean_coupling_time_step
479 os%nstep = os%nstep + 1
481 call enable_averaging(time_step, os%Time, os%MOM_CSp%diag)
482 call mech_forcing_diags(os%fluxes, time_step, os%grid, &
483 os%MOM_CSp%diag, os%forcing_CSp%handles)
484 call disable_averaging(os%MOM_CSp%diag)
486 if (os%fluxes%fluxes_used)
then 487 call enable_averaging(os%fluxes%dt_buoy_accum, os%Time, os%MOM_CSp%diag)
488 call forcing_diagnostics(os%fluxes, os%state, os%fluxes%dt_buoy_accum, &
489 os%grid, os%MOM_CSp%diag, os%forcing_CSp%handles)
490 call accumulate_net_input(os%fluxes, os%state, os%fluxes%dt_buoy_accum, &
491 os%grid, os%sum_output_CSp)
492 call disable_averaging(os%MOM_CSp%diag)
496 if ((os%Time + ((ocean_coupling_time_step)/2) > os%write_energy_time) .and. &
497 (os%MOM_CSp%t_dyn_rel_adv==0.0))
then 498 call write_energy(os%MOM_CSp%u, os%MOM_CSp%v, os%MOM_CSp%h, os%MOM_CSp%tv, &
499 os%Time, os%nstep, os%grid, os%GV, os%sum_output_CSp, &
500 os%MOM_CSp%tracer_flow_CSp)
501 os%write_energy_time = os%write_energy_time + os%energysavedays
525 subroutine add_berg_flux_to_shelf(G, fluxes, use_ice_shelf, density_ice, kv_ice, latent_heat_fusion, state, time_step, berg_area_threshold)
527 type(
forcing),
intent(inout) :: fluxes
528 type(
surface),
intent(inout) :: state
529 logical,
intent(in) :: use_ice_shelf
530 real,
intent(in) :: kv_ice
531 real,
intent(in) :: density_ice
532 real,
intent(in) :: latent_heat_fusion
533 real,
intent(in) :: time_step
534 real,
intent(in) :: berg_area_threshold
539 integer :: i, j, is, ie, js, je, isd, ied, jsd, jed
540 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
541 isd = g%isd ; jsd = g%jsd ; ied = g%ied ; jed = g%jed
547 if (.not. (((
associated(fluxes%frac_shelf_h) .and.
associated(fluxes%frac_shelf_u)) &
548 .and.(
associated(fluxes%frac_shelf_v) .and.
associated(fluxes%ustar_shelf)))&
549 .and.(
associated(fluxes%rigidity_ice_u) .and.
associated(fluxes%rigidity_ice_v))))
return 551 if (.not. ((
associated(fluxes%area_berg) .and.
associated(fluxes%ustar_berg)) .and.
associated(fluxes%mass_berg) ) )
return 553 if (.not. use_ice_shelf)
then 554 fluxes%frac_shelf_h(:,:)=0.
555 fluxes%frac_shelf_u(:,:)=0.
556 fluxes%frac_shelf_v(:,:)=0.
557 fluxes%ustar_shelf(:,:)=0.
558 fluxes%rigidity_ice_u(:,:)=0.
559 fluxes%rigidity_ice_v(:,:)=0.
562 do j=jsd,jed ;
do i=isd,ied
563 if (g%areaT(i,j) > 0.0) &
564 fluxes%frac_shelf_h(i,j) = fluxes%frac_shelf_h(i,j) + fluxes%area_berg(i,j)
565 fluxes%ustar_shelf(i,j) = fluxes%ustar_shelf(i,j) + fluxes%ustar_berg(i,j)
568 do j=jsd,jed ;
do i=isd,ied-1
569 fluxes%frac_shelf_u(i,j) = 0.0
570 if ((g%areaT(i,j) + g%areaT(i+1,j) > 0.0)) &
571 fluxes%frac_shelf_u(i,j) = fluxes%frac_shelf_u(i,j) + (((fluxes%area_berg(i,j)*g%areaT(i,j)) + (fluxes%area_berg(i+1,j)*g%areaT(i+1,j))) / &
572 (g%areaT(i,j) + g%areaT(i+1,j)))
573 fluxes%rigidity_ice_u(i,j) = fluxes%rigidity_ice_u(i,j) +((kv_ice / density_ice) * &
574 min(fluxes%mass_berg(i,j), fluxes%mass_berg(i+1,j)))
576 do j=jsd,jed-1 ;
do i=isd,ied
578 fluxes%frac_shelf_v(i,j) = 0.0
579 if ((g%areaT(i,j) + g%areaT(i,j+1) > 0.0)) &
580 fluxes%frac_shelf_v(i,j) = fluxes%frac_shelf_v(i,j) + (((fluxes%area_berg(i,j)*g%areaT(i,j)) + (fluxes%area_berg(i,j+1)*g%areaT(i,j+1))) / &
581 (g%areaT(i,j) + g%areaT(i,j+1) ))
582 fluxes%rigidity_ice_v(i,j) = fluxes%rigidity_ice_v(i,j) +((kv_ice / density_ice) * &
583 max(fluxes%mass_berg(i,j), fluxes%mass_berg(i,j+1)))
585 call pass_vector(fluxes%frac_shelf_u, fluxes%frac_shelf_v, g%domain,
to_all, cgrid_ne)
588 if (berg_area_threshold >= 0.)
then 589 do j=jsd,jed ;
do i=isd,ied
590 if (fluxes%frac_shelf_h(i,j) > berg_area_threshold)
then 592 if (
associated(fluxes%sw)) fluxes%sw(i,j) = 0.0
593 if (
associated(fluxes%lw)) fluxes%lw(i,j) = 0.0
594 if (
associated(fluxes%latent)) fluxes%latent(i,j) = 0.0
595 if (
associated(fluxes%evap)) fluxes%evap(i,j) = 0.0
601 if (
associated(state%frazil))
then 602 fraz = state%frazil(i,j) / time_step / latent_heat_fusion
603 if (
associated(fluxes%evap)) fluxes%evap(i,j) = fluxes%evap(i,j) - fraz
605 state%frazil(i,j) = 0.0
609 if (
associated(fluxes%sens)) fluxes%sens(i,j) = 0.0
610 if (
associated(fluxes%salt_flux)) fluxes%salt_flux(i,j) = 0.0
611 if (
associated(fluxes%lprec)) fluxes%lprec(i,j) = 0.0
620 character(len=*),
intent(in),
optional :: timestamp
622 if (os%MOM_CSp%t_dyn_rel_adv > 0.0)
call mom_error(warning,
"End of MOM_main reached "//&
623 "with inconsistent dynamics and advective times. Additional restart fields "//&
624 "that have not been coded yet would be required for reproducibility.")
625 if (.not.os%fluxes%fluxes_used)
call mom_error(fatal,
"ocean_model_restart "//&
626 "was called with unused buoyancy fluxes. For conservation, the ocean "//&
627 "restart files can only be created after the buoyancy forcing is applied.")
629 if (btest(os%Restart_control,1))
then 630 call save_restart(os%dirs%restart_output_dir, os%Time, os%grid, &
631 os%MOM_CSp%restart_CSp, .true., gv=os%GV)
633 os%dirs%restart_output_dir, .true.)
634 if (os%use_ice_shelf)
then 638 if (btest(os%Restart_control,0))
then 639 call save_restart(os%dirs%restart_output_dir, os%Time, os%grid, &
640 os%MOM_CSp%restart_CSp, gv=os%GV)
642 os%dirs%restart_output_dir)
643 if (os%use_ice_shelf)
then 661 type(time_type),
intent(in) :: Time
674 call mom_end(ocean_state%MOM_CSp)
675 if (ocean_state%use_ice_shelf)
call ice_shelf_end(ocean_state%Ice_shelf_CSp)
682 type(time_type),
intent(in) :: Time
683 character(len=*),
optional,
intent(in) :: directory
684 character(len=*),
optional,
intent(in) :: filename_suffix
694 character(len=200) :: restart_dir
696 if (os%MOM_CSp%t_dyn_rel_adv > 0.0)
call mom_error(warning,
"End of MOM_main reached "//&
697 "with inconsistent dynamics and advective times. Additional restart fields "//&
698 "that have not been coded yet would be required for reproducibility.")
699 if (.not.os%fluxes%fluxes_used)
call mom_error(fatal,
"ocean_model_save_restart "//&
700 "was called with unused buoyancy fluxes. For conservation, the ocean "//&
701 "restart files can only be created after the buoyancy forcing is applied.")
703 if (
present(directory))
then ; restart_dir = directory
704 else ; restart_dir = os%dirs%restart_output_dir ;
endif 706 call save_restart(restart_dir, time, os%grid, os%MOM_CSp%restart_CSp, gv=os%GV)
710 if (os%use_ice_shelf)
then 719 type(domain2d),
intent(in) :: input_domain
722 logical,
intent(in),
optional :: maskmap(:,:)
723 integer :: xsz, ysz, layout(2)
726 integer :: isc_bnd, iec_bnd, jsc_bnd, jec_bnd
728 call mpp_get_layout(input_domain,layout)
729 call mpp_get_global_domain(input_domain, xsize=xsz, ysize=ysz)
730 if(
PRESENT(maskmap))
then 731 call mpp_define_domains((/1,xsz,1,ysz/),layout,ocean_sfc%Domain, maskmap=maskmap)
733 call mpp_define_domains((/1,xsz,1,ysz/),layout,ocean_sfc%Domain)
735 call mpp_get_compute_domain(ocean_sfc%Domain, isc_bnd, iec_bnd, &
738 allocate ( ocean_sfc%t_surf (isc_bnd:iec_bnd,jsc_bnd:jec_bnd), &
739 ocean_sfc%s_surf (isc_bnd:iec_bnd,jsc_bnd:jec_bnd), &
740 ocean_sfc%u_surf (isc_bnd:iec_bnd,jsc_bnd:jec_bnd), &
741 ocean_sfc%v_surf (isc_bnd:iec_bnd,jsc_bnd:jec_bnd), &
742 ocean_sfc%sea_lev(isc_bnd:iec_bnd,jsc_bnd:jec_bnd), &
743 ocean_sfc%area (isc_bnd:iec_bnd,jsc_bnd:jec_bnd), &
744 ocean_sfc%frazil (isc_bnd:iec_bnd,jsc_bnd:jec_bnd))
746 ocean_sfc%t_surf = 0.0
747 ocean_sfc%s_surf = 0.0
748 ocean_sfc%u_surf = 0.0
749 ocean_sfc%v_surf = 0.0
750 ocean_sfc%sea_lev = 0.0
751 ocean_sfc%frazil = 0.0
753 ocean_sfc%axes = diag%axesT1%handles
761 logical,
intent(in) :: use_conT_absS
762 real,
optional,
intent(in) :: patm(:,:)
763 real,
optional,
intent(in) :: press_to_z
770 character(len=48) :: val_str
771 integer :: isc_bnd, iec_bnd, jsc_bnd, jec_bnd
772 integer :: i, j, i0, j0, is, ie, js, je
774 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
777 call mpp_get_compute_domain(ocean_sfc%Domain, isc_bnd, iec_bnd, &
779 if (
present(patm))
then 781 if (.not.
present(press_to_z))
call mom_error(fatal, &
782 'convert_state_to_ocean_type: press_to_z must be present if patm is.')
785 i0 = is - isc_bnd ; j0 = js - jsc_bnd
790 if(use_cont_abss)
then 791 do j=jsc_bnd,jec_bnd ;
do i=isc_bnd,iec_bnd
792 ocean_sfc%s_surf(i,j) = gsw_sp_from_sr(state%SSS(i+i0,j+j0))
793 ocean_sfc%t_surf(i,j) = gsw_pt_from_ct(state%SSS(i+i0,j+j0),state%SST(i+i0,j+j0)) +
celsius_kelvin_offset 796 do j=jsc_bnd,jec_bnd ;
do i=isc_bnd,iec_bnd
798 ocean_sfc%s_surf(i,j) = state%SSS(i+i0,j+j0)
802 do j=jsc_bnd,jec_bnd ;
do i=isc_bnd,iec_bnd
803 ocean_sfc%sea_lev(i,j) = state%sea_lev(i+i0,j+j0)
805 ocean_sfc%sea_lev(i,j) = ocean_sfc%sea_lev(i,j) + patm(i,j) * press_to_z
806 if (
associated(state%frazil)) &
807 ocean_sfc%frazil(i,j) = state%frazil(i+i0,j+j0)
808 ocean_sfc%area(i,j) = g%areaT(i+i0,j+j0)
811 if (ocean_sfc%stagger == agrid)
then 812 do j=jsc_bnd,jec_bnd ;
do i=isc_bnd,iec_bnd
813 ocean_sfc%u_surf(i,j) = g%mask2dT(i+i0,j+j0)*0.5*(state%u(i+i0,j+j0)+state%u(i-1+i0,j+j0))
814 ocean_sfc%v_surf(i,j) = g%mask2dT(i+i0,j+j0)*0.5*(state%v(i+i0,j+j0)+state%v(i+i0,j-1+j0))
816 elseif (ocean_sfc%stagger == bgrid_ne)
then 817 do j=jsc_bnd,jec_bnd ;
do i=isc_bnd,iec_bnd
818 ocean_sfc%u_surf(i,j) = g%mask2dBu(i+i0,j+j0)*0.5*(state%u(i+i0,j+j0)+state%u(i+i0,j+j0+1))
819 ocean_sfc%v_surf(i,j) = g%mask2dBu(i+i0,j+j0)*0.5*(state%v(i+i0,j+j0)+state%v(i+i0+1,j+j0))
821 elseif (ocean_sfc%stagger == cgrid_ne)
then 822 do j=jsc_bnd,jec_bnd ;
do i=isc_bnd,iec_bnd
823 ocean_sfc%u_surf(i,j) = g%mask2dCu(i+i0,j+j0)*state%u(i+i0,j+j0)
824 ocean_sfc%v_surf(i,j) = g%mask2dCv(i+i0,j+j0)*state%v(i+i0,j+j0)
827 write(val_str,
'(I8)') ocean_sfc%stagger
828 call mom_error(fatal,
"convert_state_to_ocean_type: "//&
829 "Ocean_sfc%stagger has the unrecognized value of "//trim(val_str))
832 if (.not.
associated(state%tr_fields,ocean_sfc%fields)) &
833 call mom_error(fatal,
'state%tr_fields is not pointing to Ocean_sfc%fields')
852 call calculate_surface_state(os%state, os%MOM_CSp%u, &
853 os%MOM_CSp%v, os%MOM_CSp%h, os%MOM_CSp%ave_ssh,&
854 os%grid, os%GV, os%MOM_CSp)
883 character(len=128) :: default_ice_restart_file, default_ocean_restart_file
884 character(len=40) :: mdl =
"ocean_model_flux_init" 887 logical :: use_OCMIP_CFCs, use_MOM_generic_tracer
890 os_is_set = .false. ;
if (
present(os)) os_is_set =
associated(os)
892 call get_mom_input(param_file, dirs_tmp, check_params=.false.)
894 call get_param(param_file, mdl,
"USE_OCMIP2_CFC", use_ocmip_cfcs, &
895 default=.false., do_not_log=.true.)
896 call get_param(param_file, mdl,
"USE_generic_tracer", use_mom_generic_tracer,&
897 default=.false., do_not_log=.true.)
901 if(.not.os_is_set)
then 902 if (use_ocmip_cfcs)
then 903 default_ice_restart_file =
'ice_ocmip2_cfc.res.nc' 904 default_ocean_restart_file =
'ocmip2_cfc.res.nc' 907 flux_type =
'air_sea_gas_flux', implementation =
'ocmip2', &
908 param = (/ 9.36e-07, 9.7561e-06 /), &
909 ice_restart_file = default_ice_restart_file, &
910 ocean_restart_file = default_ocean_restart_file, &
911 caller =
"register_OCMIP2_CFC")
913 flux_type =
'air_sea_gas_flux', implementation =
'ocmip2', &
914 param = (/ 9.36e-07, 9.7561e-06 /), &
915 ice_restart_file = default_ice_restart_file, &
916 ocean_restart_file = default_ocean_restart_file, &
917 caller =
"register_OCMIP2_CFC")
921 if (use_mom_generic_tracer)
then 922 #ifdef _USE_GENERIC_TRACER 923 call mom_generic_flux_init()
925 call mom_error(fatal, &
926 "call_tracer_register: use_MOM_generic_tracer=.true. BUT not compiled with _USE_GENERIC_TRACER")
936 use stock_constants_mod
, only : istock_water, istock_heat,istock_salt
938 integer,
intent(in) :: index
939 real,
intent(out) :: value
940 integer,
optional,
intent(in) :: time_index
946 real :: to_heat, to_mass, to_salt, PSU_to_kg
947 integer :: i, j, k, is, ie, js, je, nz, ind
950 if (.not.
associated(os))
return 951 if (.not.os%is_ocean_pe)
return 953 is = os%grid%isc ; ie = os%grid%iec
954 js = os%grid%jsc ; je = os%grid%jec ; nz = os%grid%ke
959 to_mass = os%GV%H_to_kg_m2
960 if (os%GV%Boussinesq)
then 961 do k=1,nz ;
do j=js,je ;
do i=is,ie ;
if (os%grid%mask2dT(i,j) > 0.5)
then 962 value =
value + to_mass*(os%MOM_CSp%h(i,j,k) * os%grid%areaT(i,j))
963 endif ;
enddo ;
enddo ;
enddo 967 do k=1,nz ;
do j=js,je ;
do i=is,ie ;
if (os%grid%mask2dT(i,j) > 0.5)
then 968 value =
value + to_mass * ((1.0 - psu_to_kg*os%MOM_CSp%tv%S(i,j,k))*&
969 (os%MOM_CSp%h(i,j,k) * os%grid%areaT(i,j)))
970 endif ;
enddo ;
enddo ;
enddo 974 to_heat = os%GV%H_to_kg_m2 * os%C_p
975 do k=1,nz ;
do j=js,je ;
do i=is,ie ;
if (os%grid%mask2dT(i,j) > 0.5)
then 976 value =
value + (to_heat * os%MOM_CSp%tv%T(i,j,k)) * &
977 (os%MOM_CSp%h(i,j,k)*os%grid%areaT(i,j))
978 endif ;
enddo ;
enddo ;
enddo 982 to_salt = os%GV%H_to_kg_m2 / 1000.0
983 do k=1,nz ;
do j=js,je ;
do i=is,ie ;
if (os%grid%mask2dT(i,j) > 0.5)
then 984 value =
value + (to_salt * os%MOM_CSp%tv%S(i,j,k)) * &
985 (os%MOM_CSp%h(i,j,k)*os%grid%areaT(i,j))
986 endif ;
enddo ;
enddo ;
enddo 987 case default ;
value = 0.0
996 character(len=*) ,
intent(in) :: name
997 real,
dimension(isc:,jsc:),
intent(out):: array2D
998 integer ,
intent(in) :: isc,jsc
1000 integer :: g_isc, g_iec, g_jsc, g_jec,g_isd, g_ied, g_jsd, g_jed, i, j
1002 if (.not.
associated(os))
return 1003 if (.not.os%is_ocean_pe)
return 1008 call mpp_get_compute_domain(os%grid%Domain%mpp_domain, g_isc, g_iec, g_jsc, g_jec)
1009 call mpp_get_data_domain (os%grid%Domain%mpp_domain, g_isd, g_ied, g_jsd, g_jed)
1011 g_isc = g_isc-g_isd+1 ; g_iec = g_iec-g_isd+1 ; g_jsc = g_jsc-g_jsd+1 ; g_jec = g_jec-g_jsd+1
1016 array2d(isc:,jsc:) = os%grid%areaT(g_isc:g_iec,g_jsc:g_jec)
1018 array2d(isc:,jsc:) = os%grid%mask2dT(g_isc:g_iec,g_jsc:g_jec)
1032 array2d(isc:,jsc:) = 0
1034 call mom_error(fatal,
'get_ocean_grid_data2D: unknown argument name='//name)
1043 character(len=*) ,
intent(in) :: name
1044 real ,
intent(out):: value
1046 if (.not.
associated(os))
return 1047 if (.not.os%is_ocean_pe)
return 1053 call mom_error(fatal,
'get_ocean_grid_data1D: unknown argument name='//name)
1061 character(len=*),
intent(in) :: id
1062 integer ,
intent(in) :: timestep
1064 integer :: n,m, outunit
1068 write(outunit,*)
"BEGIN CHECKSUM(ocean_type):: ", id, timestep
1069 write(outunit,100)
'ocean%t_surf ',mpp_chksum(ocn%t_surf )
1070 write(outunit,100)
'ocean%s_surf ',mpp_chksum(ocn%s_surf )
1071 write(outunit,100)
'ocean%u_surf ',mpp_chksum(ocn%u_surf )
1072 write(outunit,100)
'ocean%v_surf ',mpp_chksum(ocn%v_surf )
1073 write(outunit,100)
'ocean%sea_lev ',mpp_chksum(ocn%sea_lev)
1074 write(outunit,100)
'ocean%frazil ',mpp_chksum(ocn%frazil )
1076 do n = 1, ocn%fields%num_bcs
1077 do m = 1, ocn%fields%bc(n)%num_fields
1078 write(outunit,101)
'ocean%',trim(ocn%fields%bc(n)%name), &
1079 trim(ocn%fields%bc(n)%field(m)%name), &
1080 mpp_chksum(ocn%fields%bc(n)%field(m)%values)
1083 101
FORMAT(
" CHECKSUM::",a6,a,
'%',a,
" = ",z20)
1086 100
FORMAT(
" CHECKSUM::",a20,
" = ",z20)
subroutine, public ocean_model_init(Ocean_sfc, OS, Time_init, Time_in)
The following structure contains pointers to various fields which may be used describe the surface st...
subroutine, public ocean_model_restart(OS, timestamp)
subroutine, public initialize_mom(Time, param_file, dirs, CS, Time_in, offline_tracer_mode)
This subroutine initializes MOM.
This module implements boundary forcing for MOM6.
integer function, public aof_set_coupler_flux(name, flux_type, implementation, atm_tr_index, param, flag, ice_restart_file, ocean_restart_file, units, caller)
integer, parameter, public to_all
subroutine, public ocean_public_type_chksum(id, timestep, ocn)
Ocean grid type. See mom_grid for details.
This is the main routine for MOM.
subroutine, public ocean_stock_pe(OS, index, value, time_index)
subroutine, public tracer_flow_control_init(restart, day, G, GV, h, param_file, diag, OBC, CS, sponge_CSp, ALE_sponge_CSp, diag_to_Z_CSp, tv)
This subroutine calls all registered tracer initialization subroutines.
Provides the ocean grid type.
subroutine, public update_ocean_model(Ice_ocean_boundary, OS, Ocean_sfc, time_start_update, Ocean_coupling_time_step)
subroutine, public allocate_forcing_type(G, fluxes, stress, ustar, water, heat, shelf, press, iceberg)
Conditionally allocate fields within the forcing type.
subroutine, public call_tracer_register(HI, GV, param_file, CS, tr_Reg, restart_CS)
The following 5 subroutines and associated definitions provide the machinery to register and call the...
subroutine, public calltree_leave(mesg)
Writes a message about leaving a subroutine if call tree reporting is active.
subroutine ocean_model_data2d_get(OS, Ocean, name, array2D, isc, jsc)
This module contains I/O framework code.
subroutine, public ocean_model_flux_init(OS)
subroutine, public ice_shelf_end(CS)
Deallocates all memory associated with this module.
subroutine, public forcing_accumulate(flux_tmp, fluxes, dt, G, wt2)
Accumulate the forcing over time steps.
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 ocean_model_data1d_get(OS, Ocean, name, value)
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.
subroutine, public ocean_model_init_sfc(OS, Ocean_sfc)
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.
real, parameter, public celsius_kelvin_offset
subroutine, public ocean_model_end(Ocean_sfc, Ocean_state, Time)
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 ...
Provides subroutines for quantities specific to the equation of state.
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 add_berg_flux_to_shelf(G, fluxes, use_ice_shelf, density_ice, kv_ice, latent_heat_fusion, state, time_step, berg_area_threshold)
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 ocean_model_save_restart(OS, Time, directory, filename_suffix)
subroutine convert_state_to_ocean_type(state, Ocean_sfc, G, use_conT_absS, patm, press_to_z)
subroutine initialize_ocean_public_type(input_domain, Ocean_sfc, diag, maskmap)
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.