8 use mom_cpu_clock,
only : cpu_clock_id, cpu_clock_begin, cpu_clock_end
25 use mom_io,
only : slasher, fieldtype
26 use mom_io,
only : write_field, close_file, single_file, multiple
29 use mom_time_manager,
only : time_type, time_type_to_real, time_type_to_real, real_to_time
46 use user_shelf_init,
only : user_initialize_shelf_mass, user_update_shelf_mass
50 use time_interp_external_mod,
only : init_external_field, time_interp_external
51 use time_interp_external_mod,
only : time_interp_external_init
52 use time_manager_mod,
only : print_time
53 implicit none ;
private
55 #include <MOM_memory.h>
56 #ifdef SYMMETRIC_LAND_ICE
57 # define GRID_SYM_ .true.
59 # define GRID_SYM_ .false.
62 public shelf_calc_flux, add_shelf_flux, initialize_ice_shelf, ice_shelf_end
63 public ice_shelf_save_restart, solo_time_step, add_shelf_forces
81 real :: flux_factor = 1.0
83 character(len=128) :: restart_output_dir =
' '
88 real,
pointer,
dimension(:,:) :: &
105 real :: kd_molec_salt
106 real :: kd_molec_temp
110 real :: col_thick_melt_threshold
111 logical :: mass_from_file
120 logical :: solo_ice_sheet
122 logical :: gl_regularize
128 real :: density_ocean_avg
132 logical :: calve_to_mask
133 real :: min_thickness_simple_calve
137 real :: input_thickness
139 type(time_type) :: time
142 logical :: active_shelf_dynamics
144 logical :: override_shelf_movement
152 logical :: const_gamma
153 logical :: find_salt_root
154 logical :: constant_sea_level
161 integer :: id_melt = -1, id_exch_vel_s = -1, id_exch_vel_t = -1, &
162 id_tfreeze = -1, id_tfl_shelf = -1, &
163 id_thermal_driving = -1, id_haline_driving = -1, &
164 id_u_ml = -1, id_v_ml = -1, id_sbdry = -1, &
165 id_h_shelf = -1, id_h_mask = -1, &
166 id_surf_elev = -1, id_bathym = -1, &
167 id_area_shelf_h = -1, &
168 id_ustar_shelf = -1, id_shelf_mass = -1, id_mass_flux = -1
171 integer :: id_read_mass
173 integer :: id_read_area
184 integer :: id_clock_shelf
185 integer :: id_clock_pass
192 subroutine shelf_calc_flux(state, fluxes, Time, time_step, CS, forces)
195 type(
forcing),
intent(inout) :: fluxes
197 type(time_type),
intent(in) :: time
198 real,
intent(in) :: time_step
211 real,
dimension(SZI_(CS%grid)) :: &
212 rhoml, & !< Ocean mixed layer density [kg m-3].
213 dr0_dt, & !< Partial derivative of the mixed layer density
219 real,
dimension(SZI_(CS%grid),SZJ_(CS%grid)) :: &
220 exch_vel_t, & !< Sub-shelf thermal exchange velocity [m s-1]
223 real,
dimension(SZDI_(CS%grid),SZDJ_(CS%grid)) :: &
225 real,
dimension(SZDI_(CS%grid),SZDJ_(CS%grid)) :: &
229 real,
parameter :: vk = 0.40
230 real :: zeta_n = 0.052
232 real,
parameter :: rc = 0.20
239 real,
dimension(SZDI_(CS%grid),SZDJ_(CS%grid)) :: &
242 real :: sbdry1, sbdry2, s_a, s_b, s_c
245 real :: hbl_neut_h_molec
252 real :: i_n_star, n_star_term, absf
254 real :: dt_ustar, ds_ustar
257 real :: gam_mol_t, gam_mol_s
262 real :: sb_min, sb_max
263 real :: ds_min, ds_max
265 real :: wb_flux_new, dwb, ddwb_dwb_in
266 real :: i_gam_t, i_gam_s, dg_dwb, idens
267 real :: u_at_h, v_at_h, isqrt2
268 logical :: sb_min_set, sb_max_set
269 logical :: update_ice_vel
270 logical :: coupled_gl
273 real,
parameter :: c2_3 = 2.0/3.0
274 character(len=160) :: mesg
275 integer :: i, j, is, ie, js, je, ied, jed, it1, it3
276 real,
parameter :: rho_fw = 1000.0
278 if (.not.
associated(cs))
call mom_error(fatal,
"shelf_calc_flux: "// &
279 "initialize_ice_shelf must be called before shelf_calc_flux.")
280 call cpu_clock_begin(id_clock_shelf)
282 g => cs%grid ; us => cs%US
286 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; ied = g%ied ; jed = g%jed
287 i_zeta_n = 1.0 / zeta_n
289 i_rholf = 1.0/(cs%Rho0*lf)
291 sc = cs%kv_molec/cs%kd_molec_salt
292 pr = cs%kv_molec/cs%kd_molec_temp
294 rhocp = cs%Rho0 * cs%Cp
295 isqrt2 = 1.0/sqrt(2.0)
298 gam_mol_t = 12.5 * (pr**c2_3) - 6
299 gam_mol_s = 12.5 * (sc**c2_3) - 6
301 idens = 1.0/cs%density_ocean_avg
307 exch_vel_t(:,:) = 0.0 ; exch_vel_s(:,:) = 0.0
308 iss%tflux_shelf(:,:) = 0.0 ; iss%water_flux(:,:) = 0.0
309 iss%salt_flux(:,:) = 0.0; iss%tflux_ocn(:,:) = 0.0
310 iss%tfreeze(:,:) = 0.0
312 haline_driving(:,:) = 0.0
313 sbdry(:,:) = state%sss(:,:)
318 if (cs%override_shelf_movement)
then
319 cs%time_step = time_step
321 if (cs%mass_from_file)
call update_shelf_mass(g, cs, iss, time)
325 call hchksum(fluxes%frac_shelf_h,
"frac_shelf_h before apply melting", g%HI, haloshift=0)
326 call hchksum(state%sst,
"sst before apply melting", g%HI, haloshift=0)
327 call hchksum(state%sss,
"sss before apply melting", g%HI, haloshift=0)
328 call hchksum(state%u,
"u_ml before apply melting", g%HI, haloshift=0)
329 call hchksum(state%v,
"v_ml before apply melting", g%HI, haloshift=0)
330 call hchksum(state%ocean_mass,
"ocean_mass before apply melting", g%HI, haloshift=0)
336 do i=is,ie ; p_int(i) = cs%g_Earth * iss%mass_shelf(i,j) ;
enddo
340 rhoml(:), is, ie-is+1, cs%eqn_of_state)
342 dr0_dt, dr0_ds, is, ie-is+1, cs%eqn_of_state)
347 fluxes%ustar_shelf(i,j)= 0.0
352 if ((idens*state%ocean_mass(i,j) > cs%col_thick_melt_threshold) .and. &
353 (iss%area_shelf_h(i,j) > 0.0) .and. &
354 (cs%isthermo) .and. (state%Hml(i,j) > 0.0) )
then
362 u_at_h = state%u(i,j)
363 v_at_h = state%v(i,j)
366 fluxes%ustar_shelf(i,j) = max(cs%ustar_bg, us%m_to_Z*us%T_to_s * &
367 sqrt(cs%cdrag*((u_at_h**2 + v_at_h**2) + cs%utide(i,j)**1)))
369 ustar_h = us%Z_to_m*us%s_to_T*fluxes%ustar_shelf(i,j)
371 if (
associated(state%taux_shelf) .and.
associated(state%tauy_shelf))
then
372 state%taux_shelf(i,j) = ustar_h*ustar_h*cs%Rho0*isqrt2
373 state%tauy_shelf(i,j) = state%taux_shelf(i,j)
378 absf = 0.25*us%s_to_T*((abs(us%s_to_T*g%CoriolisBu(i,j)) + abs(us%s_to_T*g%CoriolisBu(i-1,j-1))) + &
379 (abs(us%s_to_T*g%CoriolisBu(i,j-1)) + abs(us%s_to_T*g%CoriolisBu(i-1,j))))
380 if (absf*state%Hml(i,j) <= vk*ustar_h)
then ; hbl_neut = state%Hml(i,j)
381 else ; hbl_neut = (vk*ustar_h) / absf ;
endif
382 hbl_neut_h_molec = zeta_n * ((hbl_neut * ustar_h) / (5.0 * cs%Kv_molec))
385 db_ds = (cs%g_Earth / rhoml(i)) * dr0_ds(i)
386 db_dt = (cs%g_Earth / rhoml(i)) * dr0_dt(i)
387 ln_neut = 0.0 ;
if (hbl_neut_h_molec > 1.0) ln_neut = log(hbl_neut_h_molec)
389 if (cs%find_salt_root)
then
392 s_a = cs%lambda1 * cs%Gamma_T_3EQ * cs%Cp
396 s_b = cs%Gamma_T_3EQ*cs%Cp*(cs%lambda2+cs%lambda3*p_int(i)- &
397 state%sst(i,j))-lf*cs%Gamma_T_3EQ/35.0
398 s_c = lf*(cs%Gamma_T_3EQ/35.0)*state%sss(i,j)
401 sbdry1 = (-s_b + sqrt(s_b*s_b-4*s_a*s_c))/(2*s_a)
402 sbdry2 = (-s_b - sqrt(s_b*s_b-4*s_a*s_c))/(2*s_a)
403 sbdry(i,j) = max(sbdry1, sbdry2)
405 if (sbdry(i,j) < 0.)
then
406 write(mesg,*)
'state%sss(i,j) = ',state%sss(i,j),
'S_a, S_b, S_c', s_a, s_b, s_c
407 call mom_error(warning, mesg, .true.)
408 write(mesg,*)
'I,J,Sbdry1,Sbdry2',i,j,sbdry1,sbdry2
409 call mom_error(warning, mesg, .true.)
410 call mom_error(fatal,
"shelf_calc_flux: Negative salinity (Sbdry).")
414 sbdry(i,j) = state%sss(i,j) ; sb_max_set = .false.
422 dt_ustar = (state%sst(i,j) - iss%tfreeze(i,j)) * ustar_h
423 ds_ustar = (state%sss(i,j) - sbdry(i,j)) * ustar_h
429 if (cs%const_gamma)
then
431 i_gam_t = cs%Gamma_T_3EQ
432 i_gam_s = cs%Gamma_T_3EQ/35.
434 gam_turb = i_vk * (ln_neut + (0.5 * i_zeta_n - 1.0))
435 i_gam_t = 1.0 / (gam_mol_t + gam_turb)
436 i_gam_s = 1.0 / (gam_mol_s + gam_turb)
439 wt_flux = dt_ustar * i_gam_t
440 wb_flux = db_ds * (ds_ustar * i_gam_s) + db_dt * wt_flux
442 if (wb_flux > 0.0)
then
445 n_star_term = (zeta_n/rc) * (hbl_neut * vk) / ustar_h**3
451 i_n_star = sqrt(1.0 + n_star_term * wb_flux)
452 dins_dwb = 0.5 * n_star_term / i_n_star
453 if (hbl_neut_h_molec > i_n_star**2)
then
454 gam_turb = i_vk * ((ln_neut - 2.0*log(i_n_star)) + &
455 (0.5*i_zeta_n*i_n_star - 1.0))
456 dg_dwb = i_vk * ( -2.0 / i_n_star + (0.5 * i_zeta_n)) * dins_dwb
460 gam_turb = i_vk * (0.5 * i_zeta_n*i_n_star - 1.0)
461 dg_dwb = i_vk * (0.5 * i_zeta_n) * dins_dwb
464 if (cs%const_gamma)
then
466 i_gam_t = cs%Gamma_T_3EQ
467 i_gam_s = cs%Gamma_T_3EQ/35.
469 i_gam_t = 1.0 / (gam_mol_t + gam_turb)
470 i_gam_s = 1.0 / (gam_mol_s + gam_turb)
473 wt_flux = dt_ustar * i_gam_t
474 wb_flux_new = db_ds * (ds_ustar * i_gam_s) + db_dt * wt_flux
477 dwb = wb_flux_new - wb_flux
478 if (abs(wb_flux_new - wb_flux) < &
479 1e-4*(abs(wb_flux_new) + abs(wb_flux)))
exit
481 ddwb_dwb_in = -dg_dwb * (db_ds * (ds_ustar * i_gam_s**2) + &
482 db_dt * (dt_ustar * i_gam_t**2)) - 1.0
485 wb_flux_new = wb_flux - dwb / ddwb_dwb_in
489 iss%tflux_ocn(i,j) = rhocp * wt_flux
490 exch_vel_t(i,j) = ustar_h * i_gam_t
491 exch_vel_s(i,j) = ustar_h * i_gam_s
501 if (iss%tflux_ocn(i,j) <= 0.0)
then
502 iss%water_flux(i,j) = i_lf * iss%tflux_ocn(i,j)
503 iss%tflux_shelf(i,j) = 0.0
505 if (cs%insulator)
then
507 iss%tflux_shelf(i,j) = 0.0
508 iss%water_flux(i,j) = i_lf * (- iss%tflux_shelf(i,j) + iss%tflux_ocn(i,j))
515 iss%water_flux(i,j) = iss%tflux_ocn(i,j) / &
516 (lf + cs%CP_Ice * (iss%tfreeze(i,j) - cs%Temp_Ice))
518 iss%tflux_shelf(i,j) = iss%tflux_ocn(i,j) - lf*iss%water_flux(i,j)
527 if (cs%find_salt_root)
then
531 mass_exch = exch_vel_s(i,j) * cs%Rho0
532 sbdry_it = (state%sss(i,j) * mass_exch + cs%Salin_ice * &
533 iss%water_flux(i,j)) / (mass_exch + iss%water_flux(i,j))
534 ds_it = sbdry_it - sbdry(i,j)
535 if (abs(ds_it) < 1e-4*(0.5*(state%sss(i,j) + sbdry(i,j) + 1.e-10)))
exit
538 if (ds_it < 0.0)
then
539 if (sb_max_set .and. (sbdry(i,j) > sb_max)) &
540 call mom_error(fatal,
"shelf_calc_flux: Irregular iteration for Sbdry (max).")
541 sb_max = sbdry(i,j) ; ds_max = ds_it ; sb_max_set = .true.
543 if (sb_min_set .and. (sbdry(i,j) < sb_min)) &
544 call mom_error(fatal, &
545 "shelf_calc_flux: Irregular iteration for Sbdry (min).")
546 sb_min = sbdry(i,j) ; ds_min = ds_it ; sb_min_set = .true.
549 if (sb_min_set .and. sb_max_set)
then
551 sbdry(i,j) = sb_min + (sb_max-sb_min) * &
552 (ds_min / (ds_min - ds_max))
554 sbdry(i,j) = sbdry_it
557 sbdry(i,j) = sbdry_it
568 call calculate_tfreeze(state%sss(i,j), p_int(i), iss%tfreeze(i,j), cs%eqn_of_state)
570 exch_vel_t(i,j) = cs%gamma_t
571 iss%tflux_ocn(i,j) = rhocp * exch_vel_t(i,j) * (state%sst(i,j) - iss%tfreeze(i,j))
572 iss%tflux_shelf(i,j) = 0.0
573 iss%water_flux(i,j) = i_lf * iss%tflux_ocn(i,j)
577 iss%tflux_ocn(i,j) = 0.0
587 if (cs%const_gamma)
then
588 fluxes%iceshelf_melt = iss%water_flux * (86400.0*365.0/rho_fw) * cs%flux_factor
590 fluxes%iceshelf_melt = iss%water_flux * (86400.0*365.0/cs%density_ice) * cs%flux_factor
593 do j=js,je ;
do i=is,ie
594 if ((idens*state%ocean_mass(i,j) > cs%col_thick_melt_threshold) .and. &
595 (iss%area_shelf_h(i,j) > 0.0) .and. &
596 (cs%isthermo) .and. (state%Hml(i,j) > 0.0) )
then
601 if ((cs%g_Earth * iss%mass_shelf(i,j)) < cs%Rho0*cs%cutoff_depth* &
603 iss%water_flux(i,j) = 0.0
604 fluxes%iceshelf_melt(i,j) = 0.0
607 haline_driving(i,j) = (iss%water_flux(i,j) * sbdry(i,j)) / &
608 (cs%Rho0 * exch_vel_s(i,j))
624 if ((abs(fluxes%iceshelf_melt(i,j))>0.0) .and. (fluxes%ustar_shelf(i,j) == 0.0))
then
625 write(mesg,*)
"|melt| = ",fluxes%iceshelf_melt(i,j),
" > 0 and ustar_shelf = 0. at i,j", i, j
626 call mom_error(fatal,
"shelf_calc_flux: "//trim(mesg))
634 mass_flux(:,:) = iss%water_flux(:,:) * iss%area_shelf_h(:,:)
636 if (cs%active_shelf_dynamics .or. cs%override_shelf_movement)
then
637 call cpu_clock_begin(id_clock_pass)
638 call pass_var(iss%area_shelf_h, g%domain, complete=.false.)
639 call pass_var(iss%mass_shelf, g%domain)
640 call cpu_clock_end(id_clock_pass)
644 if ( cs%override_shelf_movement .and. (.not.cs%mass_from_file))
then
645 call change_thickness_using_melt(iss, g, time_step, fluxes, cs%rho_ice, cs%debug)
648 call hchksum(iss%h_shelf,
"h_shelf after change thickness using melt", g%HI, haloshift=0, scale=us%Z_to_m)
649 call hchksum(iss%mass_shelf,
"mass_shelf after change thickness using melt", g%HI, haloshift=0)
653 if (cs%debug)
call mom_forcing_chksum(
"Before add shelf flux", fluxes, g, cs%US, haloshift=0)
655 call add_shelf_flux(g, cs, state, fluxes)
659 if (cs%active_shelf_dynamics)
then
660 update_ice_vel = .false.
661 coupled_gl = (cs%GL_couple .and. .not.cs%solo_ice_sheet)
665 call update_ice_shelf(cs%dCS, iss, g, us, time_step, time, state%ocean_mass, coupled_gl)
669 call enable_averaging(time_step,time,cs%diag)
670 if (cs%id_shelf_mass > 0)
call post_data(cs%id_shelf_mass, iss%mass_shelf, cs%diag)
671 if (cs%id_area_shelf_h > 0)
call post_data(cs%id_area_shelf_h, iss%area_shelf_h, cs%diag)
672 if (cs%id_ustar_shelf > 0)
call post_data(cs%id_ustar_shelf, fluxes%ustar_shelf, cs%diag)
673 if (cs%id_melt > 0)
call post_data(cs%id_melt, fluxes%iceshelf_melt, cs%diag)
674 if (cs%id_thermal_driving > 0)
call post_data(cs%id_thermal_driving, (state%sst-iss%tfreeze), cs%diag)
675 if (cs%id_Sbdry > 0)
call post_data(cs%id_Sbdry, sbdry, cs%diag)
676 if (cs%id_haline_driving > 0)
call post_data(cs%id_haline_driving, haline_driving, cs%diag)
677 if (cs%id_mass_flux > 0)
call post_data(cs%id_mass_flux, mass_flux, cs%diag)
678 if (cs%id_u_ml > 0)
call post_data(cs%id_u_ml, state%u, cs%diag)
679 if (cs%id_v_ml > 0)
call post_data(cs%id_v_ml, state%v, cs%diag)
680 if (cs%id_tfreeze > 0)
call post_data(cs%id_tfreeze, iss%tfreeze, cs%diag)
681 if (cs%id_tfl_shelf > 0)
call post_data(cs%id_tfl_shelf, iss%tflux_shelf, cs%diag)
682 if (cs%id_exch_vel_t > 0)
call post_data(cs%id_exch_vel_t, exch_vel_t, cs%diag)
683 if (cs%id_exch_vel_s > 0)
call post_data(cs%id_exch_vel_s, exch_vel_s, cs%diag)
684 if (cs%id_h_shelf > 0)
call post_data(cs%id_h_shelf,iss%h_shelf,cs%diag)
685 if (cs%id_h_mask > 0)
call post_data(cs%id_h_mask,iss%hmask,cs%diag)
686 call disable_averaging(cs%diag)
688 if (
present(forces))
then
689 call add_shelf_forces(g, cs, forces, do_shelf_area=(cs%active_shelf_dynamics .or. &
690 cs%override_shelf_movement))
693 call cpu_clock_end(id_clock_shelf)
695 if (cs%debug)
call mom_forcing_chksum(
"End of shelf calc flux", fluxes, g, cs%US, haloshift=0)
697 end subroutine shelf_calc_flux
700 subroutine change_thickness_using_melt(ISS, G, time_step, fluxes, rho_ice, debug)
704 real,
intent(in) :: time_step
705 type(
forcing),
intent(inout) :: fluxes
707 real,
intent(in) :: rho_ice
708 logical,
optional,
intent(in) :: debug
714 i_rho_ice = 1.0 / rho_ice
716 do j=g%jsc,g%jec ;
do i=g%isc,g%iec
717 if ((iss%hmask(i,j) == 1) .or. (iss%hmask(i,j) == 2))
then
719 if (
associated(fluxes%lprec)) fluxes%lprec(i,j) = 0.0
720 if (
associated(fluxes%sens)) fluxes%sens(i,j) = 0.0
721 if (
associated(fluxes%frac_shelf_h)) fluxes%frac_shelf_h(i,j) = 0.0
722 if (
associated(fluxes%salt_flux)) fluxes%salt_flux(i,j) = 0.0
724 if (iss%water_flux(i,j) / rho_ice * time_step < iss%h_shelf(i,j))
then
725 iss%h_shelf(i,j) = iss%h_shelf(i,j) - iss%water_flux(i,j) / rho_ice * time_step
729 iss%h_shelf(i,j) = 0.0
731 iss%area_shelf_h(i,j) = 0.0
736 call pass_var(iss%area_shelf_h, g%domain)
737 call pass_var(iss%h_shelf, g%domain)
741 do j=g%jsd,g%jed ;
do i=g%isd,g%ied
742 if ((iss%hmask(i,j) == 1) .or. (iss%hmask(i,j) == 2))
then
743 iss%mass_shelf(i,j) = iss%h_shelf(i,j)*rho_ice
747 call pass_var(iss%mass_shelf, g%domain)
749 end subroutine change_thickness_using_melt
753 subroutine add_shelf_forces(G, CS, forces, do_shelf_area)
757 logical,
optional,
intent(in) :: do_shelf_area
765 integer :: i, j, is, ie, js, je, isd, ied, jsd, jed
766 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
767 isd = g%isd ; jsd = g%jsd ; ied = g%ied ; jed = g%jed
769 if ((cs%grid%isc /= g%isc) .or. (cs%grid%iec /= g%iec) .or. &
770 (cs%grid%jsc /= g%jsc) .or. (cs%grid%jec /= g%jec)) &
771 call mom_error(fatal,
"add_shelf_forces: Incompatible ocean and ice shelf grids.")
775 find_area = .true. ;
if (
present(do_shelf_area)) find_area = do_shelf_area
779 do j=jsd,jed ;
do i=isd,ied-1
780 forces%frac_shelf_u(i,j) = 0.0
781 if ((g%areaT(i,j) + g%areaT(i+1,j) > 0.0)) &
782 forces%frac_shelf_u(i,j) = ((iss%area_shelf_h(i,j) + iss%area_shelf_h(i+1,j)) / &
783 (g%areaT(i,j) + g%areaT(i+1,j)))
785 do j=jsd,jed-1 ;
do i=isd,ied
786 forces%frac_shelf_v(i,j) = 0.0
787 if ((g%areaT(i,j) + g%areaT(i,j+1) > 0.0)) &
788 forces%frac_shelf_v(i,j) = ((iss%area_shelf_h(i,j) + iss%area_shelf_h(i,j+1)) / &
789 (g%areaT(i,j) + g%areaT(i,j+1)))
791 call pass_vector(forces%frac_shelf_u, forces%frac_shelf_v, g%domain, to_all, cgrid_ne)
795 do j=jsd,jed ;
do i=isd,ied
796 press_ice = (iss%area_shelf_h(i,j) * g%IareaT(i,j)) * (cs%g_Earth * iss%mass_shelf(i,j))
797 if (
associated(forces%p_surf))
then
798 if (.not.forces%accumulate_p_surf) forces%p_surf(i,j) = 0.0
799 forces%p_surf(i,j) = forces%p_surf(i,j) + press_ice
801 if (
associated(forces%p_surf_full))
then
802 if (.not.forces%accumulate_p_surf) forces%p_surf_full(i,j) = 0.0
803 forces%p_surf_full(i,j) = forces%p_surf_full(i,j) + press_ice
811 kv_rho_ice = cs%kv_ice / cs%density_ice
812 do j=js,je ;
do i=is-1,ie
813 if (.not.forces%accumulate_rigidity) forces%rigidity_ice_u(i,j) = 0.0
814 forces%rigidity_ice_u(i,j) = forces%rigidity_ice_u(i,j) + &
815 kv_rho_ice * min(iss%mass_shelf(i,j), iss%mass_shelf(i+1,j))
817 do j=js-1,je ;
do i=is,ie
818 if (.not.forces%accumulate_rigidity) forces%rigidity_ice_v(i,j) = 0.0
819 forces%rigidity_ice_v(i,j) = forces%rigidity_ice_v(i,j) + &
820 kv_rho_ice * min(iss%mass_shelf(i,j), iss%mass_shelf(i,j+1))
824 call uvchksum(
"rigidity_ice_[uv]", forces%rigidity_ice_u, forces%rigidity_ice_v, &
825 g%HI, symmetric=.true.)
826 call uvchksum(
"frac_shelf_[uv]", forces%frac_shelf_u, forces%frac_shelf_v, &
827 g%HI, symmetric=.true.)
830 end subroutine add_shelf_forces
833 subroutine add_shelf_pressure(G, CS, fluxes)
836 type(
forcing),
intent(inout) :: fluxes
839 integer :: i, j, is, ie, js, je, isd, ied, jsd, jed
840 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
842 if ((cs%grid%isc /= g%isc) .or. (cs%grid%iec /= g%iec) .or. &
843 (cs%grid%jsc /= g%jsc) .or. (cs%grid%jec /= g%jec)) &
844 call mom_error(fatal,
"add_shelf_pressure: Incompatible ocean and ice shelf grids.")
846 do j=js,je ;
do i=is,ie
847 press_ice = (cs%ISS%area_shelf_h(i,j) * g%IareaT(i,j)) * (cs%g_Earth * cs%ISS%mass_shelf(i,j))
848 if (
associated(fluxes%p_surf))
then
849 if (.not.fluxes%accumulate_p_surf) fluxes%p_surf(i,j) = 0.0
850 fluxes%p_surf(i,j) = fluxes%p_surf(i,j) + press_ice
852 if (
associated(fluxes%p_surf_full))
then
853 if (.not.fluxes%accumulate_p_surf) fluxes%p_surf_full(i,j) = 0.0
854 fluxes%p_surf_full(i,j) = fluxes%p_surf_full(i,j) + press_ice
858 end subroutine add_shelf_pressure
861 subroutine add_shelf_flux(G, CS, state, fluxes)
864 type(
surface),
intent(inout) :: state
865 type(
forcing),
intent(inout) :: fluxes
872 real :: delta_mass_shelf
878 real :: mean_melt_flux
881 type(time_type) :: time0
882 real,
dimension(SZDI_(G),SZDJ_(G)) :: last_mass_shelf
884 real,
dimension(SZDI_(G),SZDJ_(G)) :: last_h_shelf
886 real,
dimension(SZDI_(G),SZDJ_(G)) :: last_hmask
888 real,
dimension(SZDI_(G),SZDJ_(G)) :: last_area_shelf_h
894 real,
parameter :: rho_fw = 1000.0
895 character(len=160) :: mesg
896 integer :: i, j, is, ie, js, je, isd, ied, jsd, jed
897 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
898 isd = g%isd ; jsd = g%jsd ; ied = g%ied ; jed = g%jed
900 if ((cs%grid%isc /= g%isc) .or. (cs%grid%iec /= g%iec) .or. &
901 (cs%grid%jsc /= g%jsc) .or. (cs%grid%jec /= g%jec)) &
902 call mom_error(fatal,
"add_shelf_flux: Incompatible ocean and ice shelf grids.")
906 call add_shelf_pressure(g, cs, fluxes)
913 if (
associated(state%taux_shelf) .and.
associated(state%tauy_shelf))
then
914 call uvchksum(
"tau[xy]_shelf", state%taux_shelf, state%tauy_shelf, &
919 if (
associated(state%taux_shelf) .and.
associated(state%tauy_shelf))
then
920 call pass_vector(state%taux_shelf, state%tauy_shelf, g%domain, to_all, cgrid_ne)
942 if (cs%active_shelf_dynamics .or. cs%override_shelf_movement)
then
943 do j=jsd,jed ;
do i=isd,ied
944 if (g%areaT(i,j) > 0.0) &
945 fluxes%frac_shelf_h(i,j) = iss%area_shelf_h(i,j) * g%IareaT(i,j)
949 do j=js,je ;
do i=is,ie ;
if (iss%area_shelf_h(i,j) > 0.0)
then
950 frac_area = fluxes%frac_shelf_h(i,j)
951 if (
associated(fluxes%sw)) fluxes%sw(i,j) = 0.0
952 if (
associated(fluxes%sw_vis_dir)) fluxes%sw_vis_dir(i,j) = 0.0
953 if (
associated(fluxes%sw_vis_dif)) fluxes%sw_vis_dif(i,j) = 0.0
954 if (
associated(fluxes%sw_nir_dir)) fluxes%sw_nir_dir(i,j) = 0.0
955 if (
associated(fluxes%sw_nir_dif)) fluxes%sw_nir_dif(i,j) = 0.0
956 if (
associated(fluxes%lw)) fluxes%lw(i,j) = 0.0
957 if (
associated(fluxes%latent)) fluxes%latent(i,j) = 0.0
958 if (
associated(fluxes%evap)) fluxes%evap(i,j) = 0.0
959 if (
associated(fluxes%lprec))
then
960 if (iss%water_flux(i,j) > 0.0)
then
961 fluxes%lprec(i,j) = frac_area*iss%water_flux(i,j)*cs%flux_factor
963 fluxes%lprec(i,j) = 0.0
964 fluxes%evap(i,j) = frac_area*iss%water_flux(i,j)*cs%flux_factor
968 if (
associated(fluxes%sens)) &
969 fluxes%sens(i,j) = -frac_area*iss%tflux_ocn(i,j)*cs%flux_factor
970 if (
associated(fluxes%salt_flux)) &
971 fluxes%salt_flux(i,j) = frac_area * iss%salt_flux(i,j)*cs%flux_factor
972 endif ;
enddo ;
enddo
980 if (cs%constant_sea_level)
then
984 if (.not.
associated(fluxes%salt_flux))
allocate(fluxes%salt_flux(ie,je))
985 if (.not.
associated(fluxes%vprec))
allocate(fluxes%vprec(ie,je))
986 fluxes%salt_flux(:,:) = 0.0 ; fluxes%vprec(:,:) = 0.0
988 mean_melt_flux = 0.0; sponge_area = 0.0
989 do j=js,je ;
do i=is,ie
990 frac_area = fluxes%frac_shelf_h(i,j)
991 if (frac_area > 0.0) &
992 mean_melt_flux = mean_melt_flux + (iss%water_flux(i,j)) * iss%area_shelf_h(i,j)
995 if (g%geoLonT(i,j) >= 790.0 .AND. g%geoLonT(i,j) <= 800.0)
then
996 sponge_area = sponge_area + g%areaT(i,j)
1001 if (cs%override_shelf_movement .and. cs%mass_from_file)
then
1002 t0 = time_type_to_real(cs%Time) - cs%time_step
1006 time0 = real_to_time(t0)
1007 last_hmask(:,:) = iss%hmask(:,:) ; last_area_shelf_h(:,:) = iss%area_shelf_h(:,:)
1008 call time_interp_external(cs%id_read_mass, time0, last_mass_shelf)
1009 last_h_shelf(:,:) = last_mass_shelf(:,:) / cs%rho_ice
1012 if (cs%min_thickness_simple_calve > 0.0)
then
1013 call ice_shelf_min_thickness_calve(g, last_h_shelf, last_area_shelf_h, last_hmask, &
1014 cs%min_thickness_simple_calve)
1016 last_mass_shelf(:,:) = last_h_shelf(:,:) * cs%rho_ice
1019 shelf_mass0 = 0.0; shelf_mass1 = 0.0
1021 do j=js,je ;
do i=is,ie
1023 if (((1.0/cs%density_ocean_avg)*state%ocean_mass(i,j) > 0.1) .and. &
1024 (iss%area_shelf_h(i,j) > 0.0))
then
1025 shelf_mass0 = shelf_mass0 + (last_mass_shelf(i,j) * iss%area_shelf_h(i,j))
1026 shelf_mass1 = shelf_mass1 + (iss%mass_shelf(i,j) * iss%area_shelf_h(i,j))
1029 call sum_across_pes(shelf_mass0);
call sum_across_pes(shelf_mass1)
1030 delta_mass_shelf = (shelf_mass1 - shelf_mass0)/cs%time_step
1036 delta_mass_shelf = 0.0
1039 delta_mass_shelf = 0.0
1042 call sum_across_pes(mean_melt_flux)
1043 call sum_across_pes(sponge_area)
1046 mean_melt_flux = (mean_melt_flux+delta_mass_shelf) / sponge_area
1049 do j=js,je ;
do i=is,ie
1051 if (g%geoLonT(i,j) >= 790.0 .AND. g%geoLonT(i,j) <= 800.0)
then
1052 fluxes%vprec(i,j) = -mean_melt_flux * cs%density_ice/1000.
1053 fluxes%sens(i,j) = fluxes%vprec(i,j) * cs%Cp * cs%T0
1054 fluxes%salt_flux(i,j) = fluxes%vprec(i,j) * cs%S0*1.0e-3
1059 write(mesg,*)
'Mean melt flux (kg/(m^2 s)), dt = ', mean_melt_flux, cs%time_step
1061 call mom_forcing_chksum(
"After constant sea level", fluxes, g, cs%US, haloshift=0)
1066 end subroutine add_shelf_flux
1070 subroutine initialize_ice_shelf(param_file, ocn_grid, Time, CS, diag, forces, fluxes, Time_in, solo_ice_sheet_in)
1073 type(time_type),
intent(inout) :: time
1075 type(
diag_ctrl),
target,
intent(in) :: diag
1076 type(
forcing),
optional,
intent(inout) :: fluxes
1079 type(time_type),
optional,
intent(in) :: time_in
1080 logical,
optional,
intent(in) :: solo_ice_sheet_in
1092 real :: cdrag, drag_bg_vel
1093 logical :: new_sim, save_ic, var_force
1095 #include "version_variable.h"
1096 character(len=200) :: config
1097 character(len=200) :: ic_file,filename,inputdir
1098 character(len=40) :: mdl =
"MOM_ice_shelf"
1099 integer :: i, j, is, ie, js, je, isd, ied, jsd, jed, isdq, iedq, jsdq, jedq
1100 integer :: wd_halos(2)
1101 logical :: read_tideamp, shelf_mass_is_dynamic, debug
1102 character(len=240) :: tideamp_file
1104 if (
associated(cs))
then
1105 call mom_error(fatal,
"MOM_ice_shelf.F90, initialize_ice_shelf: "// &
1106 "called with an associated control structure.")
1114 call get_mom_input(dirs=dirs)
1117 call unit_scaling_init(param_file, cs%US)
1121 call mom_domains_init(cs%grid%domain, param_file, min_halo=wd_halos, symmetric=grid_sym_)
1124 call mom_grid_init(cs%grid, param_file)
1126 call create_dyn_horgrid(dg, cs%grid%HI)
1129 call set_grid_metrics(dg, param_file)
1133 if (
associated(ocn_grid))
then ; cs%ocn_grid => ocn_grid
1134 else ; cs%ocn_grid => cs%grid ;
endif
1141 if (is_root_pe())
then
1142 write(0,*)
'OG: ', og%isd, og%isc, og%iec, og%ied, og%jsd, og%jsc, og%jsd, og%jed
1143 write(0,*)
'IG: ', g%isd, g%isc, g%iec, g%ied, g%jsd, g%jsc, g%jsd, g%jed
1151 cs%solo_ice_sheet = .false.
1152 if (
present(solo_ice_sheet_in)) cs%solo_ice_sheet = solo_ice_sheet_in
1154 if (
present(time_in)) time = time_in
1156 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
1157 isd = g%isd ; jsd = g%jsd ; ied = g%ied ; jed = g%jed
1158 isdq = g%IsdB ; iedq = g%IedB ; jsdq = g%JsdB ; jedq = g%JedB
1160 cs%Lat_fusion = 3.34e5
1161 cs%override_shelf_movement = .false. ; cs%active_shelf_dynamics = .false.
1164 call get_param(param_file, mdl,
"DEBUG", debug, default=.false.)
1165 call get_param(param_file, mdl,
"DEBUG_IS", cs%debug, &
1166 "If true, write verbose debugging messages for the ice shelf.", &
1168 call get_param(param_file, mdl,
"DYNAMIC_SHELF_MASS", shelf_mass_is_dynamic, &
1169 "If true, the ice sheet mass can evolve with time.", &
1171 if (shelf_mass_is_dynamic)
then
1172 call get_param(param_file, mdl,
"OVERRIDE_SHELF_MOVEMENT", cs%override_shelf_movement, &
1173 "If true, user provided code specifies the ice-shelf "//&
1174 "movement instead of the dynamic ice model.", default=.false.)
1175 cs%active_shelf_dynamics = .not.cs%override_shelf_movement
1176 call get_param(param_file, mdl,
"GROUNDING_LINE_INTERPOLATE", cs%GL_regularize, &
1177 "If true, regularize the floatation condition at the "//&
1178 "grounding line as in Goldberg Holland Schoof 2009.", default=.false.)
1179 call get_param(param_file, mdl,
"GROUNDING_LINE_COUPLE", cs%GL_couple, &
1180 "If true, let the floatation condition be determined by "//&
1181 "ocean column thickness. This means that update_OD_ffrac "//&
1182 "will be called. GL_REGULARIZE and GL_COUPLE are exclusive.", &
1183 default=.false., do_not_log=cs%GL_regularize)
1184 if (cs%GL_regularize) cs%GL_couple = .false.
1187 call get_param(param_file, mdl,
"SHELF_THERMO", cs%isthermo, &
1188 "If true, use a thermodynamically interactive ice shelf.", &
1190 call get_param(param_file, mdl,
"SHELF_THREE_EQN", cs%threeeq, &
1191 "If true, use the three equation expression of "//&
1192 "consistency to calculate the fluxes at the ice-ocean "//&
1193 "interface.", default=.true.)
1194 call get_param(param_file, mdl,
"SHELF_INSULATOR", cs%insulator, &
1195 "If true, the ice shelf is a perfect insulatior "//&
1196 "(no conduction).", default=.false.)
1197 call get_param(param_file, mdl,
"MELTING_CUTOFF_DEPTH", cs%cutoff_depth, &
1198 "Depth above which the melt is set to zero (it must be >= 0) "//&
1199 "Default value won't affect the solution.", default=0.0)
1200 if (cs%cutoff_depth < 0.) &
1201 call mom_error(warning,
"Initialize_ice_shelf: MELTING_CUTOFF_DEPTH must be >= 0.")
1203 call get_param(param_file, mdl,
"CONST_SEA_LEVEL", cs%constant_sea_level, &
1204 "If true, apply evaporative, heat and salt fluxes in "//&
1205 "the sponge region. This will avoid a large increase "//&
1206 "in sea level. This option is needed for some of the "//&
1207 "ISOMIP+ experiments (Ocean3 and Ocean4). "//&
1208 "IMPORTANT: it is not currently possible to do "//&
1209 "prefect restarts using this flag.", default=.false.)
1211 call get_param(param_file, mdl,
"ISOMIP_S_SUR_SPONGE", &
1212 cs%S0,
"Surface salinity in the resoring region.", &
1213 default=33.8, do_not_log=.true.)
1215 call get_param(param_file, mdl,
"ISOMIP_T_SUR_SPONGE", &
1216 cs%T0,
"Surface temperature in the resoring region.", &
1217 default=-1.9, do_not_log=.true.)
1219 call get_param(param_file, mdl,
"SHELF_3EQ_GAMMA", cs%const_gamma, &
1220 "If true, user specifies a constant nondimensional heat-transfer coefficient "//&
1221 "(GAMMA_T_3EQ), from which the salt-transfer coefficient is then computed "//&
1222 " as GAMMA_T_3EQ/35. This is used with SHELF_THREE_EQN.", default=.false.)
1223 if (cs%const_gamma)
call get_param(param_file, mdl,
"SHELF_3EQ_GAMMA_T", cs%Gamma_T_3EQ, &
1224 "Nondimensional heat-transfer coefficient.",default=2.2e-2, &
1225 units=
"nondim.", fail_if_missing=.true.)
1227 call get_param(param_file, mdl,
"ICE_SHELF_MASS_FROM_FILE", &
1228 cs%mass_from_file,
"Read the mass of the "//&
1229 "ice shelf (every time step) from a file.", default=.false.)
1232 call get_param(param_file, mdl,
"SHELF_S_ROOT", cs%find_salt_root, &
1233 "If SHELF_S_ROOT = True, salinity at the ice/ocean interface (Sbdry) "//&
1234 "is computed from a quadratic equation. Otherwise, the previous "//&
1235 "interactive method to estimate Sbdry is used.", default=.false.)
1236 if (cs%find_salt_root)
then
1237 call get_param(param_file, mdl,
"TFREEZE_S0_P0",cs%lambda1, &
1238 "this is the freezing potential temperature at "//&
1239 "S=0, P=0.", units=
"degC", default=0.0, do_not_log=.true.)
1240 call get_param(param_file, mdl,
"DTFREEZE_DS",cs%lambda1, &
1241 "this is the derivative of the freezing potential "//&
1242 "temperature with salinity.", &
1243 units=
"degC psu-1", default=-0.054, do_not_log=.true.)
1244 call get_param(param_file, mdl,
"DTFREEZE_DP",cs%lambda3, &
1245 "this is the derivative of the freezing potential "//&
1246 "temperature with pressure.", &
1247 units=
"degC Pa-1", default=0.0, do_not_log=.true.)
1251 if (.not.cs%threeeq) &
1252 call get_param(param_file, mdl,
"SHELF_2EQ_GAMMA_T", cs%gamma_t, &
1253 "If SHELF_THREE_EQN is false, this the fixed turbulent "//&
1254 "exchange velocity at the ice-ocean interface.", &
1255 units=
"m s-1", fail_if_missing=.true.)
1257 call get_param(param_file, mdl,
"G_EARTH", cs%g_Earth, &
1258 "The gravitational acceleration of the Earth.", &
1259 units=
"m s-2", default = 9.80)
1260 call get_param(param_file, mdl,
"C_P", cs%Cp, &
1261 "The heat capacity of sea water.", units=
"J kg-1 K-1", &
1262 fail_if_missing=.true.)
1263 call get_param(param_file, mdl,
"RHO_0", cs%Rho0, &
1264 "The mean ocean density used with BOUSSINESQ true to "//&
1265 "calculate accelerations and the mass for conservation "//&
1266 "properties, or with BOUSSINSEQ false to convert some "//&
1267 "parameters from vertical units of m to kg m-2.", &
1268 units=
"kg m-3", default=1035.0)
1269 call get_param(param_file, mdl,
"C_P_ICE", cs%Cp_ice, &
1270 "The heat capacity of ice.", units=
"J kg-1 K-1", &
1273 call get_param(param_file, mdl,
"ICE_SHELF_FLUX_FACTOR", cs%flux_factor, &
1274 "Non-dimensional factor applied to shelf thermodynamic "//&
1275 "fluxes.", units=
"none", default=1.0)
1277 call get_param(param_file, mdl,
"KV_ICE", cs%kv_ice, &
1278 "The viscosity of the ice.", units=
"m2 s-1", default=1.0e10)
1279 call get_param(param_file, mdl,
"KV_MOLECULAR", cs%kv_molec, &
1280 "The molecular kinimatic viscosity of sea water at the "//&
1281 "freezing temperature.", units=
"m2 s-1", default=1.95e-6)
1282 call get_param(param_file, mdl,
"ICE_SHELF_SALINITY", cs%Salin_ice, &
1283 "The salinity of the ice inside the ice shelf.", units=
"psu", &
1285 call get_param(param_file, mdl,
"ICE_SHELF_TEMPERATURE", cs%Temp_ice, &
1286 "The temperature at the center of the ice shelf.", &
1287 units =
"degC", default=-15.0)
1288 call get_param(param_file, mdl,
"KD_SALT_MOLECULAR", cs%kd_molec_salt, &
1289 "The molecular diffusivity of salt in sea water at the "//&
1290 "freezing point.", units=
"m2 s-1", default=8.02e-10)
1291 call get_param(param_file, mdl,
"KD_TEMP_MOLECULAR", cs%kd_molec_temp, &
1292 "The molecular diffusivity of heat in sea water at the "//&
1293 "freezing point.", units=
"m2 s-1", default=1.41e-7)
1294 call get_param(param_file, mdl,
"RHO_0", cs%density_ocean_avg, &
1295 "avg ocean density used in floatation cond", &
1296 units=
"kg m-3", default=1035.)
1297 call get_param(param_file, mdl,
"DT_FORCING", cs%time_step, &
1298 "The time step for changing forcing, coupling with other "//&
1299 "components, or potentially writing certain diagnostics. "//&
1300 "The default value is given by DT.", units=
"s", default=0.0)
1302 call get_param(param_file, mdl,
"COL_THICK_MELT_THRESHOLD", cs%col_thick_melt_threshold, &
1303 "The minimum ML thickness where melting is allowed.", units=
"m", &
1306 call get_param(param_file, mdl,
"READ_TIDEAMP", read_tideamp, &
1307 "If true, read a file (given by TIDEAMP_FILE) containing "//&
1308 "the tidal amplitude with INT_TIDE_DISSIPATION.", default=.false.)
1310 call safe_alloc_ptr(cs%utide,isd,ied,jsd,jed) ; cs%utide(:,:) = 0.0
1312 if (read_tideamp)
then
1313 call get_param(param_file, mdl,
"TIDEAMP_FILE", tideamp_file, &
1314 "The path to the file containing the spatially varying "//&
1315 "tidal amplitudes.", &
1316 default=
"tideamp.nc")
1317 call get_param(param_file, mdl,
"INPUTDIR", inputdir, default=
".")
1318 inputdir = slasher(inputdir)
1319 tideamp_file = trim(inputdir) // trim(tideamp_file)
1320 call mom_read_data(tideamp_file,
'tideamp',cs%utide,g%domain,timelevel=1)
1322 call get_param(param_file, mdl,
"UTIDE", utide, &
1323 "The constant tidal amplitude used with INT_TIDE_DISSIPATION.", &
1324 units=
"m s-1", default=0.0)
1325 cs%utide(:,:) = utide
1328 call eos_init(param_file, cs%eqn_of_state)
1332 if (cs%active_shelf_dynamics)
then
1334 call get_param(param_file, mdl,
"DENSITY_ICE", cs%density_ice, &
1335 "A typical density of ice.", units=
"kg m-3", default=917.0)
1337 call get_param(param_file, mdl,
"INPUT_FLUX_ICE_SHELF", cs%input_flux, &
1338 "volume flux at upstream boundary", units=
"m2 s-1", default=0.)
1339 call get_param(param_file, mdl,
"INPUT_THICK_ICE_SHELF", cs%input_thickness, &
1340 "flux thickness at upstream boundary", units=
"m", default=1000.)
1343 call get_param(param_file, mdl,
"DENSITY_ICE", cs%density_ice, &
1344 "A typical density of ice.", units=
"kg m-3", default=900.0)
1346 cs%rho_ice = cs%density_ice*us%Z_to_m
1347 call get_param(param_file, mdl,
"MIN_THICKNESS_SIMPLE_CALVE", &
1348 cs%min_thickness_simple_calve, &
1349 "Min thickness rule for the very simple calving law",&
1350 units=
"m", default=0.0, scale=us%m_to_Z)
1352 call get_param(param_file, mdl,
"USTAR_SHELF_BG", cs%ustar_bg, &
1353 "The minimum value of ustar under ice sheves.", &
1354 units=
"m s-1", default=0.0, scale=us%m_to_Z*us%T_to_s)
1355 call get_param(param_file, mdl,
"CDRAG_SHELF", cdrag, &
1356 "CDRAG is the drag coefficient relating the magnitude of "//&
1357 "the velocity field to the surface stress.", units=
"nondim", &
1360 if (cs%ustar_bg <= 0.0)
then
1361 call get_param(param_file, mdl,
"DRAG_BG_VEL_SHELF", drag_bg_vel, &
1362 "DRAG_BG_VEL is either the assumed bottom velocity (with "//&
1363 "LINEAR_DRAG) or an unresolved velocity that is "//&
1364 "combined with the resolved velocity to estimate the "//&
1365 "velocity magnitude.", units=
"m s-1", default=0.0, scale=us%m_to_Z*us%T_to_s)
1366 if (cs%cdrag*drag_bg_vel > 0.0) cs%ustar_bg = sqrt(cs%cdrag)*drag_bg_vel
1370 call ice_shelf_state_init(cs%ISS, cs%grid)
1374 if (.not. cs%solo_ice_sheet)
then
1375 call mom_mesg(
"MOM_ice_shelf.F90, initialize_ice_shelf: allocating fluxes.")
1379 if (
present(fluxes)) &
1380 call allocate_forcing_type(cs%ocn_grid, fluxes, ustar=.true., shelf=.true., &
1381 press=.true., water=cs%isthermo, heat=cs%isthermo)
1382 if (
present(forces)) &
1383 call allocate_mech_forcing(cs%ocn_grid, forces, ustar=.true., shelf=.true., press=.true.)
1385 call mom_mesg(
"MOM_ice_shelf.F90, initialize_ice_shelf: allocating fluxes in solo mode.")
1386 if (
present(fluxes)) &
1387 call allocate_forcing_type(g, fluxes, ustar=.true., shelf=.true., press=.true.)
1388 if (
present(forces)) &
1389 call allocate_mech_forcing(g, forces, ustar=.true., shelf=.true., press=.true.)
1393 call mom_initialize_topography(dg%bathyT, g%max_depth, dg, param_file)
1394 call rescale_dyn_horgrid_bathymetry(dg, us%Z_to_m)
1397 call mom_initialize_rotation(dg%CoriolisBu, dg, param_file, us)
1399 call copy_dyngrid_to_mom_grid(dg, cs%grid)
1401 call destroy_dyn_horgrid(dg)
1404 call restart_init(param_file, cs%restart_CSp,
"Shelf.res")
1406 "Ice shelf mass",
"kg m-2")
1408 "Ice shelf area in cell",
"m2")
1410 "ice sheet/shelf thickness",
"m")
1412 "Height unit conversion factor",
"Z meter-1")
1413 if (cs%active_shelf_dynamics)
then
1415 "ice sheet/shelf thickness mask" ,
"none")
1420 call register_ice_shelf_dyn_restarts(g, param_file, cs%dCS, cs%restart_CSp)
1431 cs%restart_output_dir = dirs%restart_output_dir
1434 if ((dirs%input_filename(1:1) ==
'n') .and. &
1435 (len_trim(dirs%input_filename) == 1)) new_sim = .true.
1437 if (cs%override_shelf_movement .and. cs%mass_from_file)
then
1440 call initialize_shelf_mass(g, param_file, cs, iss)
1444 call initialize_ice_thickness(iss%h_shelf, iss%area_shelf_h, iss%hmask, g, us, param_file)
1447 do j=g%jsd,g%jed ;
do i=g%isd,g%ied
1448 if ((iss%hmask(i,j) == 1) .or. (iss%hmask(i,j) == 2))
then
1449 iss%mass_shelf(i,j) = iss%h_shelf(i,j)*cs%rho_ice
1453 if (cs%min_thickness_simple_calve > 0.0) &
1454 call ice_shelf_min_thickness_calve(g, iss%h_shelf, iss%area_shelf_h, iss%hmask, &
1455 cs%min_thickness_simple_calve)
1459 if (cs%active_shelf_dynamics)
then
1469 if (new_sim .and. (.not. (cs%override_shelf_movement .and. cs%mass_from_file)))
then
1472 call initialize_ice_thickness(iss%h_shelf, iss%area_shelf_h, iss%hmask, g, us, param_file)
1475 do j=g%jsd,g%jed ;
do i=g%isd,g%ied
1476 if ((iss%hmask(i,j) == 1) .or. (iss%hmask(i,j) == 2))
then
1477 iss%mass_shelf(i,j) = iss%h_shelf(i,j)*cs%rho_ice
1482 elseif (.not.new_sim)
then
1484 call mom_mesg(
"MOM_ice_shelf.F90, initialize_ice_shelf: Restoring ice shelf from file.")
1485 call restore_state(dirs%input_filename, dirs%restart_input_dir, time, &
1488 if ((us%m_to_Z_restart /= 0.0) .and. (us%m_to_Z_restart /= us%m_to_Z))
then
1489 z_rescale = us%m_to_Z / us%m_to_Z_restart
1490 do j=g%jsc,g%jec ;
do i=g%isc,g%iec
1491 iss%h_shelf(i,j) = z_rescale * iss%h_shelf(i,j)
1499 call cpu_clock_begin(id_clock_pass)
1500 call pass_var(iss%area_shelf_h, g%domain)
1501 call pass_var(iss%h_shelf, g%domain)
1502 call pass_var(iss%mass_shelf, g%domain)
1505 call cpu_clock_end(id_clock_pass)
1507 do j=jsd,jed ;
do i=isd,ied
1508 if (iss%area_shelf_h(i,j) > g%areaT(i,j))
then
1509 call mom_error(warning,
"Initialize_ice_shelf: area_shelf_h exceeds G%areaT.")
1510 iss%area_shelf_h(i,j) = g%areaT(i,j)
1513 if (
present(fluxes))
then ;
do j=jsd,jed ;
do i=isd,ied
1514 if (g%areaT(i,j) > 0.0) fluxes%frac_shelf_h(i,j) = iss%area_shelf_h(i,j) / g%areaT(i,j)
1515 enddo ;
enddo ;
endif
1518 call hchksum(fluxes%frac_shelf_h,
"IS init: frac_shelf_h", g%HI, haloshift=0)
1521 if (
present(forces)) &
1522 call add_shelf_forces(g, cs, forces, do_shelf_area=.not.cs%solo_ice_sheet)
1524 if (
present(fluxes))
call add_shelf_pressure(g, cs, fluxes)
1526 if (cs%active_shelf_dynamics .and. .not.cs%isthermo)
then
1527 iss%water_flux(:,:) = 0.0
1530 if (shelf_mass_is_dynamic) &
1531 call initialize_ice_shelf_dyn(param_file, time, iss, cs%dCS, g, us, diag, new_sim, solo_ice_sheet_in)
1533 call fix_restart_unit_scaling(us)
1535 call get_param(param_file, mdl,
"SAVE_INITIAL_CONDS", save_ic, &
1536 "If true, save the ice shelf initial conditions.", &
1538 if (save_ic)
call get_param(param_file, mdl,
"SHELF_IC_OUTPUT_FILE", ic_file,&
1539 "The name-root of the output file for the ice shelf "//&
1540 "initial conditions.", default=
"MOM_Shelf_IC")
1542 if (save_ic .and. .not.((dirs%input_filename(1:1) ==
'r') .and. &
1543 (len_trim(dirs%input_filename) == 1)))
then
1544 call save_restart(dirs%output_directory, cs%Time, g, &
1545 cs%restart_CSp, filename=ic_file)
1549 cs%id_area_shelf_h = register_diag_field(
'ocean_model',
'area_shelf_h', cs%diag%axesT1, cs%Time, &
1550 'Ice Shelf Area in cell',
'meter-2')
1551 cs%id_shelf_mass = register_diag_field(
'ocean_model',
'shelf_mass', cs%diag%axesT1, cs%Time, &
1552 'mass of shelf',
'kg/m^2')
1553 cs%id_h_shelf = register_diag_field(
'ocean_model',
'h_shelf', cs%diag%axesT1, cs%Time, &
1554 'ice shelf thickness',
'm', conversion=us%Z_to_m)
1555 cs%id_mass_flux = register_diag_field(
'ocean_model',
'mass_flux', cs%diag%axesT1,&
1556 cs%Time,
'Total mass flux of freshwater across the ice-ocean interface.',
'kg/s')
1557 cs%id_melt = register_diag_field(
'ocean_model',
'melt', cs%diag%axesT1, cs%Time, &
1558 'Ice Shelf Melt Rate',
'm yr-1')
1559 cs%id_thermal_driving = register_diag_field(
'ocean_model',
'thermal_driving', cs%diag%axesT1, cs%Time, &
1560 'pot. temp. in the boundary layer minus freezing pot. temp. at the ice-ocean interface.',
'Celsius')
1561 cs%id_haline_driving = register_diag_field(
'ocean_model',
'haline_driving', cs%diag%axesT1, cs%Time, &
1562 'salinity in the boundary layer minus salinity at the ice-ocean interface.',
'psu')
1563 cs%id_Sbdry = register_diag_field(
'ocean_model',
'sbdry', cs%diag%axesT1, cs%Time, &
1564 'salinity at the ice-ocean interface.',
'psu')
1565 cs%id_u_ml = register_diag_field(
'ocean_model',
'u_ml', cs%diag%axesCu1, cs%Time, &
1566 'Eastward vel. in the boundary layer (used to compute ustar)',
'm s-1')
1567 cs%id_v_ml = register_diag_field(
'ocean_model',
'v_ml', cs%diag%axesCv1, cs%Time, &
1568 'Northward vel. in the boundary layer (used to compute ustar)',
'm s-1')
1569 cs%id_exch_vel_s = register_diag_field(
'ocean_model',
'exch_vel_s', cs%diag%axesT1, cs%Time, &
1570 'Sub-shelf salinity exchange velocity',
'm s-1')
1571 cs%id_exch_vel_t = register_diag_field(
'ocean_model',
'exch_vel_t', cs%diag%axesT1, cs%Time, &
1572 'Sub-shelf thermal exchange velocity',
'm s-1')
1573 cs%id_tfreeze = register_diag_field(
'ocean_model',
'tfreeze', cs%diag%axesT1, cs%Time, &
1574 'In Situ Freezing point at ice shelf interface',
'degC')
1575 cs%id_tfl_shelf = register_diag_field(
'ocean_model',
'tflux_shelf', cs%diag%axesT1, cs%Time, &
1576 'Heat conduction into ice shelf',
'W m-2')
1577 cs%id_ustar_shelf = register_diag_field(
'ocean_model',
'ustar_shelf', cs%diag%axesT1, cs%Time, &
1578 'Fric vel under shelf',
'm/s', conversion=us%Z_to_m*us%s_to_T)
1579 if (cs%active_shelf_dynamics)
then
1580 cs%id_h_mask = register_diag_field(
'ocean_model',
'h_mask', cs%diag%axesT1, cs%Time, &
1581 'ice shelf thickness mask',
'none')
1584 id_clock_shelf = cpu_clock_id(
'Ice shelf', grain=clock_component)
1585 id_clock_pass = cpu_clock_id(
' Ice shelf halo updates', grain=clock_routine)
1587 end subroutine initialize_ice_shelf
1590 subroutine initialize_shelf_mass(G, param_file, CS, ISS, new_sim)
1596 logical,
optional,
intent(in) :: new_sim
1598 integer :: i, j, is, ie, js, je
1599 logical :: read_shelf_area, new_sim_2
1600 character(len=240) :: config, inputdir, shelf_file, filename
1601 character(len=120) :: shelf_mass_var
1602 character(len=120) :: shelf_area_var
1603 character(len=40) :: mdl =
"MOM_ice_shelf"
1604 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
1606 new_sim_2 = .true. ;
if (
present(new_sim)) new_sim_2 = new_sim
1608 call get_param(param_file, mdl,
"ICE_SHELF_CONFIG", config, &
1609 "A string that specifies how the ice shelf is "//&
1610 "initialized. Valid options include:\n"//&
1611 " \tfile\t Read from a file.\n"//&
1612 " \tzero\t Set shelf mass to 0 everywhere.\n"//&
1613 " \tUSER\t Call USER_initialize_shelf_mass.\n", &
1614 fail_if_missing=.true.)
1616 select case ( trim(config) )
1619 call time_interp_external_init()
1621 call get_param(param_file, mdl,
"INPUTDIR", inputdir, default=
".")
1622 inputdir = slasher(inputdir)
1624 call get_param(param_file, mdl,
"SHELF_FILE", shelf_file, &
1625 "If DYNAMIC_SHELF_MASS = True, OVERRIDE_SHELF_MOVEMENT = True "//&
1626 "and ICE_SHELF_MASS_FROM_FILE = True, this is the file from "//&
1627 "which to read the shelf mass and area.", &
1628 default=
"shelf_mass.nc")
1629 call get_param(param_file, mdl,
"SHELF_MASS_VAR", shelf_mass_var, &
1630 "The variable in SHELF_FILE with the shelf mass.", &
1631 default=
"shelf_mass")
1632 call get_param(param_file, mdl,
"READ_SHELF_AREA", read_shelf_area, &
1633 "If true, also read the area covered by ice-shelf from SHELF_FILE.", &
1636 filename = trim(slasher(inputdir))//trim(shelf_file)
1637 call log_param(param_file, mdl,
"INPUTDIR/SHELF_FILE", filename)
1639 cs%id_read_mass = init_external_field(filename, shelf_mass_var, &
1640 domain=g%Domain%mpp_domain, verbose=cs%debug)
1642 if (read_shelf_area)
then
1643 call get_param(param_file, mdl,
"SHELF_AREA_VAR", shelf_area_var, &
1644 "The variable in SHELF_FILE with the shelf area.", &
1645 default=
"shelf_area")
1647 cs%id_read_area = init_external_field(filename,shelf_area_var, &
1648 domain=g%Domain%mpp_domain)
1651 if (.not.
file_exists(filename, g%Domain))
call mom_error(fatal, &
1652 " initialize_shelf_mass: Unable to open "//trim(filename))
1655 do j=js,je ;
do i=is,ie
1656 iss%mass_shelf(i,j) = 0.0
1657 iss%area_shelf_h(i,j) = 0.0
1661 call user_initialize_shelf_mass(iss%mass_shelf, iss%area_shelf_h, &
1662 iss%h_shelf, iss%hmask, g, cs%US, cs%user_CS, param_file, new_sim_2)
1664 case default ;
call mom_error(fatal,
"initialize_ice_shelf: "// &
1665 "Unrecognized ice shelf setup "//trim(config))
1668 end subroutine initialize_shelf_mass
1671 subroutine update_shelf_mass(G, CS, ISS, Time)
1675 type(time_type),
intent(in) :: Time
1678 integer :: i, j, is, ie, js, je
1679 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
1681 call time_interp_external(cs%id_read_mass, time, iss%mass_shelf)
1683 do j=js,je ;
do i=is,ie
1684 iss%area_shelf_h(i,j) = 0.0
1686 if (iss%mass_shelf(i,j) > 0.0)
then
1687 iss%area_shelf_h(i,j) = g%areaT(i,j)
1688 iss%h_shelf(i,j) = iss%mass_shelf(i,j) / cs%rho_ice
1696 if (cs%min_thickness_simple_calve > 0.0)
then
1697 call ice_shelf_min_thickness_calve(g, iss%h_shelf, iss%area_shelf_h, iss%hmask, &
1698 cs%min_thickness_simple_calve)
1701 call pass_var(iss%area_shelf_h, g%domain)
1702 call pass_var(iss%h_shelf, g%domain)
1704 call pass_var(iss%mass_shelf, g%domain)
1706 end subroutine update_shelf_mass
1709 subroutine ice_shelf_save_restart(CS, Time, directory, time_stamped, filename_suffix)
1711 type(time_type),
intent(in) :: time
1712 character(len=*),
optional,
intent(in) :: directory
1714 logical,
optional,
intent(in) :: time_stamped
1716 character(len=*),
optional,
intent(in) :: filename_suffix
1720 character(len=200) :: restart_dir
1724 if (
present(directory))
then ; restart_dir = directory
1725 else ; restart_dir = cs%restart_output_dir ;
endif
1727 call save_restart(restart_dir, time, cs%grid, cs%restart_CSp, time_stamped)
1729 end subroutine ice_shelf_save_restart
1732 subroutine ice_shelf_end(CS)
1735 if (.not.
associated(cs))
return
1737 call ice_shelf_state_end(cs%ISS)
1739 if (cs%active_shelf_dynamics)
call ice_shelf_dyn_end(cs%dCS)
1743 end subroutine ice_shelf_end
1746 subroutine solo_time_step(CS, time_step, nsteps, Time, min_time_step_in)
1748 real,
intent(in) :: time_step
1749 integer,
intent(inout) :: nsteps
1750 type(time_type),
intent(inout) :: time
1751 real,
optional,
intent(in) :: min_time_step_in
1758 integer :: is, iec, js, jec, i, j
1759 real :: time_step_remain
1760 real :: time_step_int, min_time_step
1761 character(len=240) :: mesg
1762 logical :: update_ice_vel
1763 logical :: coupled_gl
1769 is = g%isc ; iec = g%iec ; js = g%jsc ; jec = g%jec
1771 time_step_remain = time_step
1772 if (
present (min_time_step_in))
then
1773 min_time_step = min_time_step_in
1775 min_time_step = 1000.0
1778 write (mesg,*)
"TIME in ice shelf call, yrs: ", time_type_to_real(time)/(365. * 86400.)
1779 call mom_mesg(
"solo_time_step: "//mesg)
1781 do while (time_step_remain > 0.0)
1785 time_step_int = min(ice_time_step_cfl(cs%dCS, iss, g), time_step)
1787 write (mesg,*)
"Ice model timestep = ", time_step_int,
" seconds"
1788 if (time_step_int < min_time_step)
then
1789 call mom_error(fatal,
"MOM_ice_shelf:solo_time_step: abnormally small timestep "//mesg)
1791 call mom_mesg(
"solo_time_step: "//mesg)
1794 if (time_step_int >= time_step_remain)
then
1795 time_step_int = time_step_remain
1796 time_step_remain = 0.0
1798 time_step_remain = time_step_remain - time_step_int
1803 update_ice_vel = ((time_step_int > min_time_step) .or. (time_step_int >= time_step))
1804 coupled_gl = .false.
1806 call update_ice_shelf(cs%dCS, iss, g, us, time_step_int, time, must_update_vel=update_ice_vel)
1808 call enable_averaging(time_step,time,cs%diag)
1809 if (cs%id_area_shelf_h > 0)
call post_data(cs%id_area_shelf_h, iss%area_shelf_h, cs%diag)
1810 if (cs%id_h_shelf > 0)
call post_data(cs%id_h_shelf, iss%h_shelf, cs%diag)
1811 if (cs%id_h_mask > 0)
call post_data(cs%id_h_mask, iss%hmask, cs%diag)
1812 call disable_averaging(cs%diag)
1816 end subroutine solo_time_step