@@ -17,7 +17,7 @@ module MOM_state_initialization
1717use MOM_file_parser, only : log_version
1818use MOM_get_input, only : directories
1919use MOM_grid, only : ocean_grid_type, isPointInCell
20- use MOM_interface_heights, only : find_eta, dz_to_thickness
20+ use MOM_interface_heights, only : find_eta, dz_to_thickness, dz_to_thickness_simple
2121use MOM_io, only : file_exists, field_size, MOM_read_data, MOM_read_vector, slasher
2222use MOM_open_boundary, only : ocean_OBC_type, open_boundary_init, set_tracer_data
2323use MOM_open_boundary, only : OBC_NONE
@@ -1125,7 +1125,7 @@ subroutine trim_for_ice(PF, G, GV, US, ALE_CSp, tv, h, just_read)
11251125 ! of temperature within each layer [C ~> degC]
11261126 character (len= 200 ) :: inputdir, filename, p_surf_file, p_surf_var ! Strings for file/path
11271127 real :: scale_factor ! A file-dependent scaling factor for the input pressure [various].
1128- real :: min_thickness ! The minimum layer thickness, recast into Z units [Z ~> m].
1128+ real :: min_thickness ! The minimum layer thickness [H ~> m or kg m-2 ].
11291129 real :: z_tolerance ! The tolerance with which to find the depth matching a specified pressure [Z ~> m].
11301130 integer :: i, j, k
11311131 integer :: default_answer_date ! The default setting for the various ANSWER_DATE flags.
@@ -1155,7 +1155,7 @@ subroutine trim_for_ice(PF, G, GV, US, ALE_CSp, tv, h, just_read)
11551155 " file SURFACE_PRESSURE_FILE into a surface pressure." , &
11561156 units= " file dependent" , default= 1 ., do_not_log= just_read)
11571157 call get_param(PF, mdl, " MIN_THICKNESS" , min_thickness, ' Minimum layer thickness' , &
1158- units= ' m' , default= 1.e-3 , scale= US % m_to_Z , do_not_log= just_read)
1158+ units= ' m' , default= 1.e-3 , scale= GV % m_to_H , do_not_log= just_read)
11591159 call get_param(PF, mdl, " TRIM_IC_Z_TOLERANCE" , z_tolerance, &
11601160 " The tolerance with which to find the depth matching the specified " // &
11611161 " surface pressure with TRIM_IC_FOR_P_SURF." , &
@@ -1312,7 +1312,7 @@ subroutine cut_off_column_top(nk, tv, GV, US, G_earth, depth, min_thickness, T,
13121312 type (unit_scale_type), intent (in ) :: US ! < A dimensional unit scaling type
13131313 real , intent (in ) :: G_earth ! < Gravitational acceleration [L2 Z-1 T-2 ~> m s-2]
13141314 real , intent (in ) :: depth ! < Depth of ocean column [Z ~> m].
1315- real , intent (in ) :: min_thickness ! < Smallest thickness allowed [Z ~> m].
1315+ real , intent (in ) :: min_thickness ! < Smallest thickness allowed [H ~> m or kg m-2 ].
13161316 real , dimension (nk), intent (inout ) :: T ! < Layer mean temperature [C ~> degC]
13171317 real , dimension (nk), intent (in ) :: T_t ! < Temperature at top of layer [C ~> degC]
13181318 real , dimension (nk), intent (in ) :: T_b ! < Temperature at bottom of layer [C ~> degC]
@@ -1335,51 +1335,75 @@ subroutine cut_off_column_top(nk, tv, GV, US, G_earth, depth, min_thickness, T,
13351335 real , dimension (nk) :: h0, h1 ! Initial and remapped layer thicknesses [H ~> m or kg m-2]
13361336 real , dimension (nk) :: S0, S1 ! Initial and remapped layer salinities [S ~> ppt]
13371337 real , dimension (nk) :: T0, T1 ! Initial and remapped layer temperatures [C ~> degC]
1338- real :: P_t, P_b ! Top and bottom pressures [R L2 T-2 ~> Pa]
1338+ real :: P_t, P_b ! Top and bottom pressures [R L2 T-2 ~> Pa]
13391339 real :: z_out, e_top ! Interface height positions [Z ~> m]
1340+ real :: min_dz ! The minimum thickness in depth units [Z ~> m]
1341+ real :: dh_surf_rem ! The remaining thickness to remove in non-Bousinesq mode [H ~> kg m-2]
13401342 logical :: answers_2018
13411343 integer :: k
13421344
13431345 answers_2018 = .true. ; if (present (remap_answer_date)) answers_2018 = (remap_answer_date < 20190101 )
13441346
1345- ! Calculate original interface positions
1346- e(nk+1 ) = - depth
1347- do k= nk,1 ,- 1
1348- e(K) = e(K+1 ) + GV% H_to_Z* h(k)
1349- h0(k) = h(nk+1 - k) ! Keep a copy to use in remapping
1350- enddo
1347+ ! Keep a copy of the initial thicknesses in reverse order to use in remapping
1348+ do k= 1 ,nk ; h0(k) = h(nk+1 - k) ; enddo
13511349
1352- P_t = 0 .
1353- e_top = e(1 )
1354- do k= 1 ,nk
1355- call find_depth_of_pressure_in_cell(T_t(k), T_b(k), S_t(k), S_b(k), e(K), e(K+1 ), &
1356- P_t, p_surf, GV% Rho0, G_earth, tv% eqn_of_state, &
1357- US, P_b, z_out, z_tol= z_tol)
1358- if (z_out>= e(K)) then
1359- ! Imposed pressure was less that pressure at top of cell
1360- exit
1361- elseif (z_out<= e(K+1 )) then
1362- ! Imposed pressure was greater than pressure at bottom of cell
1363- e_top = e(K+1 )
1364- else
1365- ! Imposed pressure was fell between pressures at top and bottom of cell
1366- e_top = z_out
1367- exit
1368- endif
1369- P_t = P_b
1370- enddo
1371- if (e_top< e(1 )) then
1372- ! Clip layers from the top down, if at all
1373- do K= 1 ,nk
1374- if (e(K) > e_top) then
1375- ! Original e(K) is too high
1376- e(K) = e_top
1377- e_top = e_top - min_thickness ! Next interface must be at least this deep
1350+ if (GV% Boussinesq) then
1351+ min_dz = GV% H_to_Z * min_thickness
1352+ ! Calculate original interface positions
1353+ e(nk+1 ) = - depth
1354+ do k= nk,1 ,- 1
1355+ e(K) = e(K+1 ) + GV% H_to_Z* h(k)
1356+ enddo
1357+
1358+ P_t = 0 .
1359+ e_top = e(1 )
1360+ do k= 1 ,nk
1361+ call find_depth_of_pressure_in_cell(T_t(k), T_b(k), S_t(k), S_b(k), e(K), e(K+1 ), &
1362+ P_t, p_surf, GV% Rho0, G_earth, tv% eqn_of_state, &
1363+ US, P_b, z_out, z_tol= z_tol)
1364+ if (z_out>= e(K)) then
1365+ ! Imposed pressure was less that pressure at top of cell
1366+ exit
1367+ elseif (z_out<= e(K+1 )) then
1368+ ! Imposed pressure was greater than pressure at bottom of cell
1369+ e_top = e(K+1 )
1370+ else
1371+ ! Imposed pressure was fell between pressures at top and bottom of cell
1372+ e_top = z_out
1373+ exit
13781374 endif
1379- ! This layer needs trimming
1380- h(k) = GV% Z_to_H * max ( min_thickness, e(K) - e(K+1 ) )
1381- if (e(K) < e_top) exit ! No need to go further
1375+ P_t = P_b
13821376 enddo
1377+ if (e_top< e(1 )) then
1378+ ! Clip layers from the top down, if at all
1379+ do K= 1 ,nk
1380+ if (e(K) > e_top) then
1381+ ! Original e(K) is too high
1382+ e(K) = e_top
1383+ e_top = e_top - min_dz ! Next interface must be at least this deep
1384+ endif
1385+ ! This layer needs trimming
1386+ h(k) = max ( min_thickness, GV% Z_to_H * (e(K) - e(K+1 )) )
1387+ if (e(K) < e_top) exit ! No need to go further
1388+ enddo
1389+ endif
1390+ else
1391+ ! In non-Bousinesq mode, we are already in mass units so the calculation is much easier.
1392+ if (p_surf > 0.0 ) then
1393+ dh_surf_rem = p_surf * GV% RZ_to_H / G_earth
1394+ do k= 1 ,nk
1395+ if (h(k) <= min_thickness) then ! This layer has no mass to remove.
1396+ cycle
1397+ elseif ((h(k) - min_thickness) < dh_surf_rem) then ! This layer should be removed entirely.
1398+ dh_surf_rem = dh_surf_rem - (h(k) - min_thickness)
1399+ h(k) = min_thickness
1400+ else ! This is the last layer that should be removed.
1401+ h(k) = h(k) - dh_surf_rem
1402+ dh_surf_rem = 0.0
1403+ exit
1404+ endif
1405+ enddo
1406+ endif
13831407 endif
13841408
13851409 ! Now we need to remap but remapping assumes the surface is at the
@@ -1867,16 +1891,18 @@ subroutine initialize_sponges_file(G, GV, US, use_temperature, tv, u, v, depth_t
18671891 ! ! overrides any value set for Time.
18681892 ! Local variables
18691893 real , allocatable , dimension (:,:,:) :: eta ! The target interface heights [Z ~> m].
1894+ real , allocatable , dimension (:,:,:) :: dz ! The target interface thicknesses in height units [Z ~> m]
18701895 real , allocatable , dimension (:,:,:) :: h ! The target interface thicknesses [H ~> m or kg m-2].
18711896
18721897 real , dimension (SZI_(G),SZJ_(G),SZK_(GV)) :: &
18731898 tmp, & ! A temporary array for temperatures [C ~> degC] or other tracers.
18741899 tmp2 ! A temporary array for salinities [S ~> ppt]
18751900 real , dimension (SZI_(G),SZJ_(G)) :: &
18761901 tmp_2d ! A temporary array for mixed layer densities [R ~> kg m-3]
1877- real , allocatable , dimension (:,:,:) :: tmp_tr ! A temporary array for reading sponge target fields
1878- ! on the vertical grid of the input file, used for both
1879- ! temperatures [C ~> degC] and salinities [S ~> ppt]
1902+ real , allocatable , dimension (:,:,:) :: tmp_T ! A temporary array for reading sponge target temperatures
1903+ ! on the vertical grid of the input file [C ~> degC]
1904+ real , allocatable , dimension (:,:,:) :: tmp_S ! A temporary array for reading sponge target salinities
1905+ ! on the vertical grid of the input file [S ~> ppt]
18801906 real , allocatable , dimension (:,:,:) :: tmp_u ! Temporary array for reading sponge target zonal
18811907 ! velocities on the vertical grid of the input file [L T-1 ~> m s-1]
18821908 real , allocatable , dimension (:,:,:) :: tmp_v ! Temporary array for reading sponge target meridional
@@ -1897,6 +1923,7 @@ subroutine initialize_sponges_file(G, GV, US, use_temperature, tv, u, v, depth_t
18971923 character (len= 40 ) :: mdl = " initialize_sponges_file"
18981924 character (len= 200 ) :: damping_file, uv_damping_file, state_file, state_uv_file ! Strings for filenames
18991925 character (len= 200 ) :: filename, inputdir ! Strings for file/path and path.
1926+ type (verticalGrid_type) :: GV_loc ! A temporary vertical grid structure
19001927
19011928 logical :: use_ALE ! True if ALE is being used, False if in layered mode
19021929 logical :: time_space_interp_sponge ! If true use sponge data that need to be interpolated in both
@@ -2069,35 +2096,51 @@ subroutine initialize_sponges_file(G, GV, US, use_temperature, tv, u, v, depth_t
20692096 call MOM_error(FATAL," initialize_sponge_file: Array size mismatch for sponge data." )
20702097 nz_data = siz(3 )- 1
20712098 allocate (eta(isd:ied,jsd:jed,nz_data+1 ))
2072- allocate (h (isd:ied,jsd:jed,nz_data))
2099+ allocate (dz (isd:ied,jsd:jed,nz_data))
20732100 call MOM_read_data(filename, eta_var, eta(:,:,:), G% Domain, scale= US% m_to_Z)
20742101 do j= js,je ; do i= is,ie
2075- eta(i,j,nz +1 ) = - depth_tot(i,j)
2102+ eta(i,j,nz_data +1 ) = - depth_tot(i,j)
20762103 enddo ; enddo
2077- do k= nz ,1 ,- 1 ; do j= js,je ; do i= is,ie
2104+ do k= nz_data ,1 ,- 1 ; do j= js,je ; do i= is,ie
20782105 if (eta(i,j,K) < (eta(i,j,K+1 ) + GV% Angstrom_Z)) &
20792106 eta(i,j,K) = eta(i,j,K+1 ) + GV% Angstrom_Z
20802107 enddo ; enddo ; enddo
2081- do k= 1 ,nz ; do j= js,je ; do i= is,ie
2082- h (i,j,k) = GV % Z_to_H * ( eta(i,j,k)- eta(i,j,k+1 ) )
2108+ do k= 1 ,nz_data ; do j= js,je ; do i= is,ie
2109+ dz (i,j,k) = eta(i,j,k)- eta(i,j,k+1 )
20832110 enddo ; enddo ; enddo
2111+ deallocate (eta)
2112+
2113+ allocate (h(isd:ied,jsd:jed,nz_data))
2114+ if (use_temperature) then
2115+ allocate (tmp_T(isd:ied,jsd:jed,nz_data))
2116+ allocate (tmp_S(isd:ied,jsd:jed,nz_data))
2117+ call MOM_read_data(filename, potemp_var, tmp_T(:,:,:), G% Domain, scale= US% degC_to_C)
2118+ call MOM_read_data(filename, salin_var, tmp_S(:,:,:), G% Domain, scale= US% ppt_to_S)
2119+ endif
2120+
2121+ GV_loc = GV ; GV_loc% ke = nz_data
2122+ if (use_temperature .and. associated (tv% eqn_of_state)) then
2123+ call dz_to_thickness(dz, tmp_T, tmp_S, tv% eqn_of_state, h, G, GV_loc, US)
2124+ else
2125+ call dz_to_thickness_simple(dz, h, G, GV_loc, US, layer_mode= .true. )
2126+ endif
2127+
20842128 if (sponge_uv) then
20852129 call initialize_ALE_sponge(Idamp, G, GV, param_file, ALE_CSp, h, nz_data, Idamp_u, Idamp_v)
20862130 else
20872131 call initialize_ALE_sponge(Idamp, G, GV, param_file, ALE_CSp, h, nz_data)
20882132 endif
2089- deallocate (eta)
2090- deallocate (h)
20912133 if (use_temperature) then
2092- allocate (tmp_tr(isd:ied,jsd:jed,nz_data))
2093- call MOM_read_data(filename, potemp_var, tmp_tr(:,:,:), G% Domain, scale= US% degC_to_C)
2094- call set_up_ALE_sponge_field(tmp_tr, G, GV, tv% T, ALE_CSp, ' temp' , &
2134+ call set_up_ALE_sponge_field(tmp_T, G, GV, tv% T, ALE_CSp, ' temp' , &
20952135 sp_long_name= ' temperature' , sp_unit= ' degC s-1' )
2096- call MOM_read_data(filename, salin_var, tmp_tr(:,:,:), G% Domain, scale= US% ppt_to_S)
2097- call set_up_ALE_sponge_field(tmp_tr, G, GV, tv% S, ALE_CSp, ' salt' , &
2136+ call set_up_ALE_sponge_field(tmp_S, G, GV, tv% S, ALE_CSp, ' salt' , &
20982137 sp_long_name= ' salinity' , sp_unit= ' g kg-1 s-1' )
2099- deallocate (tmp_tr)
2138+ deallocate (tmp_S)
2139+ deallocate (tmp_T)
21002140 endif
2141+ deallocate (h)
2142+ deallocate (dz)
2143+
21012144 if (sponge_uv) then
21022145 filename = trim (inputdir)// trim (state_uv_file)
21032146 call log_param(param_file, mdl, " INPUTDIR/SPONGE_STATE_UV_FILE" , filename)
@@ -2735,11 +2778,32 @@ subroutine MOM_temp_salt_initialize_from_Z(h, tv, depth_tot, G, GV, US, PF, just
27352778 enddo ; enddo
27362779 deallocate ( tmp_mask_in )
27372780
2781+ ! Convert input thicknesses to units of H. In non-Boussinesq mode this is done by inverting
2782+ ! integrals of specific volume in pressure, so it can be expensive.
2783+ tv_loc = tv
2784+ tv_loc% T = > tmpT1dIn
2785+ tv_loc% S = > tmpS1dIn
2786+ GV_loc = GV
2787+ GV_loc% ke = nkd
2788+ call dz_to_thickness(dz1, tv_loc, h1, G, GV_loc, US)
2789+
27382790 ! Build the target grid (and set the model thickness to it)
2739- ! This call can be more general but is hard-coded for z* coordinates... ????
2791+
27402792 call ALE_initRegridding( GV, US, G% max_depth, PF, mdl, regridCS ) ! sets regridCS
2793+ call initialize_remapping( remapCS, remappingScheme, boundary_extrapolation= .false. , answer_date= remap_answer_date )
27412794
2742- if (.not. remap_general) then
2795+ ! Now remap from source grid to target grid, first setting reconstruction parameters
2796+ if (remap_general) then
2797+ call set_regrid_params( regridCS, min_thickness= 0 . )
2798+ allocate ( dz_interface(isd:ied,jsd:jed,nkd+1 ) ) ! Need for argument to regridding_main() but is not used
2799+
2800+ call regridding_preadjust_reqs(regridCS, do_conv_adj, ignore)
2801+ if (do_conv_adj) call convective_adjustment(G, GV_loc, h1, tv_loc)
2802+ call regridding_main( remapCS, regridCS, G, GV_loc, h1, tv_loc, h, dz_interface, &
2803+ frac_shelf_h= frac_shelf_h )
2804+
2805+ deallocate ( dz_interface )
2806+ else
27432807 ! This is the old way of initializing to z* coordinates only
27442808 allocate ( hTarget(nz) )
27452809 hTarget = getCoordinateResolution( regridCS )
@@ -2759,36 +2823,11 @@ subroutine MOM_temp_salt_initialize_from_Z(h, tv, depth_tot, G, GV, US, PF, just
27592823 enddo ; enddo
27602824 deallocate ( hTarget )
27612825
2762- do k= 1 ,nkd ; do j= js,je ; do i= is,ie
2763- h1(i,j,k) = GV% Z_to_H* dz1(i,j,k)
2764- enddo ; enddo ; enddo
2765- do k= 1 ,nz ; do j= js,je ; do i= is,ie
2766- h(i,j,k) = GV% Z_to_H* dz(i,j,k)
2767- enddo ; enddo ; enddo
2826+ ! This is a simple conversion of the target grid to thickness units that may not be
2827+ ! appropriate in non-Boussinesq mode.
2828+ call dz_to_thickness_simple(dz, h, G, GV, US)
27682829 endif
27692830
2770- ! Now remap from source grid to target grid, first setting reconstruction parameters
2771- call initialize_remapping( remapCS, remappingScheme, boundary_extrapolation= .false. , answer_date= remap_answer_date )
2772- if (remap_general) then
2773- call set_regrid_params( regridCS, min_thickness= 0 . )
2774- tv_loc = tv
2775- tv_loc% T = > tmpT1dIn
2776- tv_loc% S = > tmpS1dIn
2777- GV_loc = GV
2778- GV_loc% ke = nkd
2779- allocate ( dz_interface(isd:ied,jsd:jed,nkd+1 ) ) ! Need for argument to regridding_main() but is not used
2780-
2781- ! Convert thicknesses to units of H, in non-Boussinesq mode by inverting integrals of
2782- ! specific volume in pressure
2783- call dz_to_thickness(dz1, tv_loc, h1, G, GV_loc, US)
2784-
2785- call regridding_preadjust_reqs(regridCS, do_conv_adj, ignore)
2786- if (do_conv_adj) call convective_adjustment(G, GV_loc, h1, tv_loc)
2787- call regridding_main( remapCS, regridCS, G, GV_loc, h1, tv_loc, h, dz_interface, &
2788- frac_shelf_h= frac_shelf_h )
2789-
2790- deallocate ( dz_interface )
2791- endif
27922831 call ALE_remap_scalar(remapCS, G, GV, nkd, h1, tmpT1dIn, h, tv% T, all_cells= remap_full_column, &
27932832 old_remap= remap_old_alg, answer_date= remap_answer_date )
27942833 call ALE_remap_scalar(remapCS, G, GV, nkd, h1, tmpS1dIn, h, tv% S, all_cells= remap_full_column, &
@@ -3085,7 +3124,7 @@ subroutine MOM_state_init_tests(G, GV, US, tv)
30853124 write (0 ,* ) ' ==================================================================== '
30863125 write (0 ,* ) ' '
30873126 write (0 ,* ) GV% H_to_m* h(:)
3088- call cut_off_column_top(nk, tv, GV, US, GV% g_Earth, - e(nk+1 ), GV% Angstrom_Z , &
3127+ call cut_off_column_top(nk, tv, GV, US, GV% g_Earth, - e(nk+1 ), GV% Angstrom_H , &
30893128 T, T_t, T_b, S, S_t, S_b, 0.5 * P_tot, h, remap_CS, z_tol= z_tol)
30903129 write (0 ,* ) GV% H_to_m* h(:)
30913130
0 commit comments