SCALE-RM
scale_ocean_phy_ice_simple.F90
Go to the documentation of this file.
1 !-------------------------------------------------------------------------------
10 !-------------------------------------------------------------------------------
11 #include "scalelib.h"
13  !-----------------------------------------------------------------------------
14  !
15  !++ used modules
16  !
17  use scale_precision
18  use scale_io
19  use scale_prof
20  !-----------------------------------------------------------------------------
21  implicit none
22  private
23  !-----------------------------------------------------------------------------
24  !
25  !++ Public procedure
26  !
27  public :: ocean_phy_ice_setup
28  public :: ocean_phy_ice_fraction
29  public :: ocean_phy_ice_adjustment
30  public :: ocean_phy_ice_simple
31 
32  !-----------------------------------------------------------------------------
33  !
34  !++ Public parameters & variables
35  !
36  !-----------------------------------------------------------------------------
37  !
38  !++ Private procedure
39  !
40  !-----------------------------------------------------------------------------
41  !
42  !++ Private parameters & variables
43  !
44  real(RP), public :: ocean_phy_ice_freezetemp = 271.35_rp ! freezing temperature of sea ice [K]
45  real(RP), public :: ocean_phy_ice_density = 1000.0_rp ! density of sea ice [kg/m3]
46 
47  real(RP), private :: ocean_phy_ice_mass_critical = 1600.0_rp ! ice amount for fraction = 1 [kg/m2]
48  real(RP), private :: ocean_phy_ice_mass_limit = 50000.0_rp ! maximum ice amount [kg/m2]
49  real(RP), private :: ocean_phy_ice_fraction_limit = 1.0_rp ! maximum ice fraction [1]
50  real(RP), private :: ocean_phy_ice_dt_max = 5.e-2_rp ! maximum delta ice temperature [K/s]
51 
52  logical, private :: ocean_phy_ice_nudging = .false.
53  real(DP), private :: ocean_phy_ice_nudging_tausec
54  logical, private :: ocean_phy_ice_offline_mode = .false.
55 
56  !-----------------------------------------------------------------------------
57 contains
58  !-----------------------------------------------------------------------------
59  subroutine ocean_phy_ice_setup
60  use scale_prc, only: &
61  prc_abort
62  use scale_const, only: &
63  undef => const_undef
64  use scale_calendar, only: &
66  use scale_file_external_input, only: &
69  implicit none
70 
71  real(DP) :: OCEAN_PHY_ICE_nudging_tau = 0.0_dp ! Relaxation time
72  character(len=H_SHORT) :: OCEAN_PHY_ICE_nudging_tau_unit = "SEC"
73  character(len=H_LONG) :: OCEAN_PHY_ICE_nudging_basename(file_external_input_file_limit) = ''
74  logical :: OCEAN_PHY_ICE_nudging_enable_periodic_year = .false.
75  logical :: OCEAN_PHY_ICE_nudging_enable_periodic_month = .false.
76  logical :: OCEAN_PHY_ICE_nudging_enable_periodic_day = .false.
77  integer :: OCEAN_PHY_ICE_nudging_step_fixed = 0
78  real(RP) :: OCEAN_PHY_ICE_nudging_offset = 0.0_rp
79  real(RP) :: OCEAN_PHY_ICE_nudging_defval != UNDEF
80  logical :: OCEAN_PHY_ICE_nudging_check_coordinates = .true.
81  integer :: OCEAN_PHY_ICE_nudging_step_limit = 0
82 
83  namelist / param_ocean_phy_ice / &
85  ocean_phy_ice_mass_critical, &
86  ocean_phy_ice_mass_limit, &
87  ocean_phy_ice_fraction_limit, &
88  ocean_phy_ice_dt_max!, &
89 ! OCEAN_PHY_ICE_nudging, &
90 ! OCEAN_PHY_ICE_nudging_tau, &
91 ! OCEAN_PHY_ICE_nudging_tau_unit, &
92 ! OCEAN_PHY_ICE_nudging_basename, &
93 ! OCEAN_PHY_ICE_nudging_enable_periodic_year, &
94 ! OCEAN_PHY_ICE_nudging_enable_periodic_month, &
95 ! OCEAN_PHY_ICE_nudging_enable_periodic_day, &
96 ! OCEAN_PHY_ICE_nudging_step_fixed, &
97 ! OCEAN_PHY_ICE_nudging_offset, &
98 ! OCEAN_PHY_ICE_nudging_defval, &
99 ! OCEAN_PHY_ICE_nudging_check_coordinates, &
100 ! OCEAN_PHY_ICE_nudging_step_limit
101 
102  integer :: ierr
103  !---------------------------------------------------------------------------
104 
105  log_newline
106  log_info("OCEAN_PHY_ICE_setup",*) 'Setup'
107 
108  ocean_phy_ice_nudging_defval = undef
109 
110  !--- read namelist
111  rewind(io_fid_conf)
112  read(io_fid_conf,nml=param_ocean_phy_ice,iostat=ierr)
113  if( ierr < 0 ) then !--- missing
114  log_info("OCEAN_PHY_ICE_setup",*) 'Not found namelist. Default used.'
115  elseif( ierr > 0 ) then !--- fatal error
116  log_error("OCEAN_PHY_ICE_setup",*) 'Not appropriate names in namelist PARAM_OCEAN_PHY_ICE. Check!'
117  call prc_abort
118  endif
119  log_nml(param_ocean_phy_ice)
120 
121  log_newline
122  log_info("OCEAN_PHY_ICE_setup",*) 'Ice amount for frac. = 1 [kg/m2] : ', ocean_phy_ice_mass_critical
123  if ( ocean_phy_ice_nudging ) then
124  call calendar_unit2sec( ocean_phy_ice_nudging_tausec, ocean_phy_ice_nudging_tau, ocean_phy_ice_nudging_tau_unit )
125 
126  log_info("OCEAN_PHY_ICE_setup",*) 'Use nudging for sea ice fraction : ON'
127  log_info("OCEAN_PHY_ICE_setup",*) 'Relaxation time Tau [sec] : ', ocean_phy_ice_nudging_tausec
128 
129  if ( ocean_phy_ice_nudging_tausec == 0.0_rp ) then
130  ocean_phy_ice_offline_mode = .true.
131  log_info("OCEAN_PHY_ICE_setup",*) 'Tau=0 means that sea ice is completely replaced by the external data.'
132  endif
133 
134  if ( ocean_phy_ice_nudging_basename(1) == '' ) then
135  log_error("OCEAN_PHY_ICE_setup",*) 'OCEAN_PHY_ICE_nudging_basename is necessary. STOP'
136  call prc_abort
137  endif
138  else
139  log_info("OCEAN_PHY_ICE_setup",*) 'Use nudging for sea ice fraction : OFF'
140  endif
141 
142  if ( ocean_phy_ice_nudging ) then
143  call file_external_input_regist( ocean_phy_ice_nudging_basename(:), & ! [IN]
144  'OCEAN_ICE_FRAC', & ! [IN]
145  'XY', & ! [IN]
146  ocean_phy_ice_nudging_enable_periodic_year, & ! [IN]
147  ocean_phy_ice_nudging_enable_periodic_month, & ! [IN]
148  ocean_phy_ice_nudging_enable_periodic_day, & ! [IN]
149  ocean_phy_ice_nudging_step_fixed, & ! [IN]
150  ocean_phy_ice_nudging_offset, & ! [IN]
151  ocean_phy_ice_nudging_defval, & ! [IN]
152  ocean_phy_ice_nudging_check_coordinates, & ! [IN]
153  ocean_phy_ice_nudging_step_limit ) ! [IN]
154  endif
155 
156  return
157  end subroutine ocean_phy_ice_setup
158 
159  !-----------------------------------------------------------------------------
160  subroutine ocean_phy_ice_fraction( &
161  OIA, OIS, OIE, &
162  OJA, OJS, OJE, &
163  ICE_MASS, &
164  ICE_FRAC )
165  implicit none
166 
167  integer, intent(in) :: OIA, OIS, OIE
168  integer, intent(in) :: OJA, OJS, OJE
169  real(RP), intent(in) :: ICE_MASS(oia,oja) ! sea ice amount [kg/m2]
170  real(RP), intent(out) :: ICE_FRAC(oia,oja) ! sea ice area fraction [1]
171 
172  integer :: i, j
173  !---------------------------------------------------------------------------
174 
175  do j = ojs, oje
176  do i = ois, oie
177  ice_frac(i,j) = ice_mass(i,j) / ocean_phy_ice_mass_critical
178 
179  ice_frac(i,j) = min( sqrt( max( ice_frac(i,j), 0.0_rp ) ), ocean_phy_ice_fraction_limit )
180  enddo
181  enddo
182 
183  return
184  end subroutine ocean_phy_ice_fraction
185 
186  !-----------------------------------------------------------------------------
187  subroutine ocean_phy_ice_adjustment( &
188  OIA, OIS, OIE, &
189  OJA, OJS, OJE, &
190  calc_flag, &
191  OCEAN_DEPTH, &
192  OCEAN_TEMP, &
193  ICE_TEMP, &
194  ICE_MASS )
195  use scale_const, only: &
196  cl => const_cl, &
197  ci => const_ci, &
198  emelt => const_emelt, &
199  dwatr => const_dwatr
200  implicit none
201 
202  integer, intent(in) :: OIA, OIS, OIE
203  integer, intent(in) :: OJA, OJS, OJE
204  logical, intent(in) :: calc_flag (oia,oja) ! to decide calculate or not
205  real(RP), intent(in) :: OCEAN_DEPTH ! depth of the first layer of the ocean
206  real(RP), intent(inout) :: OCEAN_TEMP(oia,oja) ! ocean temperature [K]
207  real(RP), intent(inout) :: ICE_TEMP (oia,oja) ! sea ice temperature [K]
208  real(RP), intent(inout) :: ICE_MASS (oia,oja) ! sea ice amount [kg/m2]
209 
210  real(RP) :: ICE_MASS_diff
211  real(RP) :: ICE_MASS_prev
212  real(RP) :: factor
213  real(RP) :: sw
214 
215  integer :: i, j
216  !---------------------------------------------------------------------------
217 
218  !$omp parallel do &
219  !$omp private(ICE_MASS_diff,ICE_MASS_prev,factor,sw)
220  do j = ojs, oje
221  do i = ois, oie
222  sw = 0.5_rp + sign(0.5_rp, ocean_temp(i,j) - ocean_phy_ice_freezetemp) ! 1: melt, 0: freeze
223  factor = cl * dwatr * ocean_depth &
224  / ( emelt + sw * ci * ( ocean_phy_ice_freezetemp - ice_temp(i,j) ) )
225 
226  if ( calc_flag(i,j) ) then
227  ! update ice mass
228  ice_mass_diff = ( ocean_phy_ice_freezetemp - ocean_temp(i,j) ) * factor ! [kg/m2/s], positive is freezing
229  ice_mass_prev = ice_mass(i,j)
230  ice_mass(i,j) = min( max( ice_mass(i,j) + ice_mass_diff, 0.0_rp ), ocean_phy_ice_mass_limit ) ! update mass w/ limiter
231  ice_mass_diff = ice_mass(i,j) - ice_mass_prev
232 
233  ! update ocean temperature
234  ocean_temp(i,j) = ocean_temp(i,j) + ice_mass_diff / factor
235 
236  ! update ice temperature
237  if ( ice_mass(i,j) > 0.0_rp ) then
238  if ( ice_mass_diff > 0.0_rp ) then ! when ice increases, new ice have the temperature at freezing point (when the limiter does not work)
239  ice_temp(i,j) = ( ice_temp(i,j) * ice_mass_prev &
240  + ocean_phy_ice_freezetemp * ice_mass_diff &
241  + ( ocean_phy_ice_freezetemp - ocean_temp(i,j) ) * ice_mass_diff * cl / ci & ! due to the limiter
242  ) / ice_mass(i,j)
243  endif
244  else ! fill value
245  ice_temp(i,j) = ocean_phy_ice_freezetemp
246  endif
247  endif
248  enddo
249  enddo
250 
251  return
252  end subroutine ocean_phy_ice_adjustment
253 
254  !-----------------------------------------------------------------------------
256  subroutine ocean_phy_ice_simple( &
257  OIA, OIS, OIE, &
258  OJA, OJS, OJE, &
259  sflx_QV, &
260  sflx_rain, &
261  sflx_snow, &
262  sflx_hbalance, &
263  subsfc_temp, &
264  TC_dz, &
265  ICE_TEMP, &
266  ICE_MASS, &
267  calc_flag, &
268  dt, &
269  ICE_TEMP_t, &
270  ICE_MASS_t, &
271  sflx_G, &
272  sflx_water, &
273  sflx_ice )
274  use scale_prc, only: &
275  prc_abort
276  use scale_const, only: &
277  const_ci, &
279  use scale_file_external_input, only: &
280  file_external_input_update
281  implicit none
282 
283  integer, intent(in) :: OIA, OIS, OIE
284  integer, intent(in) :: OJA, OJS, OJE
285  real(RP), intent(in) :: sflx_QV (oia,oja) ! water vapor flux [kg/m2/s]
286  real(RP), intent(in) :: sflx_rain (oia,oja) ! rain flux [kg/m2/s]
287  real(RP), intent(in) :: sflx_snow (oia,oja) ! snow flux [kg/m2/s]
288  real(RP), intent(in) :: sflx_hbalance(oia,oja) ! surface heat flux balance [J/m2/s] (negative)
289  real(RP), intent(in) :: subsfc_temp (oia,oja) ! subsurface temperature [K]
290  real(RP), intent(in) :: TC_dz (oia,oja) ! Thermal conductance [K/m]
291  real(RP), intent(in) :: ICE_TEMP (oia,oja) ! sea ice temperature [K]
292  real(RP), intent(in) :: ICE_MASS (oia,oja) ! sea ice amount [kg/m2]
293  logical, intent(in) :: calc_flag (oia,oja) ! to decide calculate or not
294  real(DP), intent(in) :: dt
295  real(RP), intent(out) :: ICE_TEMP_t (oia,oja) ! tendency of sea ice temperature [K/s]
296  real(RP), intent(out) :: ICE_MASS_t (oia,oja) ! tendency of sea ice amount [kg/m2/s]
297  real(RP), intent(out) :: SFLX_G (oia,oja) ! heat flux from sea ice to subsurface
298  real(RP), intent(out) :: SFLX_water (oia,oja) ! liquid water flux from sea ice to subsurface
299  real(RP), intent(out) :: SFLX_ice (oia,oja) ! ice water flux from sea ice to subsurface
300 
301  real(RP) :: mass_budget ! [kg/m2/s]
302  real(RP) :: ICE_MASS_new ! [kg/m2]
303  real(RP) :: ICE_MASS_new2 ! [kg/m2]
304  real(RP) :: heat_budget ! [J/m2/s]
305  real(RP) :: heat_budget_new ! [J/m2/s]
306  real(RP) :: gflx ! [J/m2/s]
307  real(RP) :: ICE_TEMP_new ! [K]
308  real(RP) :: heatcapacity ! [J/m2/K]
309  real(RP) :: heating ! [J/m2/s]
310  real(RP) :: cooling ! [J/m2/s]
311  real(RP) :: sflx_melt ! [kg/m2/s]
312  real(RP) :: dt_RP
313 
314  integer :: i, j
315  !---------------------------------------------------------------------------
316 
317  log_progress(*) 'ocean / physics / seaice'
318 
319  dt_rp = real(dt,kind=rp)
320 
321  !$omp parallel do &
322  !$omp private(mass_budget,ICE_MASS_new,ICE_MASS_new2, &
323  !$omp heat_budget,heat_budget_new,gflx,ICE_TEMP_new,heatcapacity,heating,cooling, &
324  !$omp sflx_melt)
325  do j = ojs, oje
326  do i = ois, oie
327  if ( calc_flag(i,j) ) then
328  ! mass balance
329  mass_budget = -sflx_qv(i,j) + sflx_rain(i,j) + sflx_snow(i,j)
330  ice_mass_new = max( ice_mass(i,j) + mass_budget * dt_rp, 0.0_rp )
331  mass_budget = mass_budget - ( ice_mass_new - ice_mass(i,j) ) / dt_rp ! residual
332 
333  ! heat balance
334  gflx = ( subsfc_temp(i,j) - ice_temp(i,j) ) * tc_dz(i,j)
335  heat_budget = sflx_hbalance(i,j) & ! SWD - SWU + LWD - LWU - SH - LH
336  + gflx & ! heat flux from ocean
337  + sflx_rain(i,j) * const_emelt ! rain freezing
338 
339  ice_temp_new = ice_temp(i,j)
340  heatcapacity = const_ci * ice_mass_new
341 
342  ! heating ice
343  if ( heat_budget > 0.0_rp .AND. ice_mass_new > 0.0_rp ) then
344  heating = max( ocean_phy_ice_freezetemp - ice_temp(i,j), 0.0_rp ) / dt_rp * heatcapacity
345  heat_budget_new = max( heat_budget - heating, 0.0_rp )
346  ice_temp_new = ice_temp(i,j) + ( heat_budget - heat_budget_new ) / heatcapacity * dt_rp
347  heat_budget = heat_budget_new
348  endif
349 
350  ! cooling ice
351  if ( heat_budget < 0.0_rp .AND. ice_mass_new > 0.0_rp ) then
352  !! cooling limiter: tiny ice does not cooled faster than thermal conductance of ice, residual heat flux goes ocean
353  !ICE_TEMP_new = max( ICE_TEMP(i,j) + heat_budget / heatcapacity * dt_RP, 0.0_RP )
354  !cooling = max( heat_budget, ( ICE_TEMP_new - ICE_TEMP(i,j) ) * TC_dZ(i,j) )
355 
356  ! cooling limiter: tiny ice does not cooled faster than the limit (-0.05K/s), residual heat flux goes ocean
357  cooling = max( heat_budget, -ocean_phy_ice_dt_max * heatcapacity )
358 
359  ice_temp_new = ice_temp(i,j) + cooling / heatcapacity * dt_rp
360  heat_budget = heat_budget - cooling
361  endif
362 
363  ! melting ice
364  sflx_melt = max( heat_budget / const_emelt, 0.0_rp ) ! only for positive heat flux
365  ice_mass_new2 = max( ice_mass_new - sflx_melt * dt_rp, 0.0_rp )
366  sflx_melt = ( ice_mass_new - ice_mass_new2 ) / dt_rp
367  heat_budget = heat_budget - sflx_melt * const_emelt
368  mass_budget = mass_budget + sflx_melt
369 
370  ! ice to ocean flux
371  sflx_g(i,j) = heat_budget - gflx
372  sflx_water(i,j) = mass_budget
373  sflx_ice(i,j) = 0.0_rp
374 
375  ice_mass_t(i,j) = ( ice_mass_new2 - ice_mass(i,j) ) / dt_rp
376  ice_temp_t(i,j) = ( ice_temp_new - ice_temp(i,j) ) / dt_rp
377  else
378  sflx_g(i,j) = 0.0_rp
379  sflx_water(i,j) = 0.0_rp
380  sflx_ice(i,j) = 0.0_rp
381  ice_mass_t(i,j) = 0.0_rp
382  ice_temp_t(i,j) = 0.0_rp
383  endif
384  enddo
385  enddo
386 
387  return
388  end subroutine ocean_phy_ice_simple
389 
subroutine, public calendar_unit2sec(second, value, unit)
Convert several units to second.
real(rp), parameter, public const_ci
specific heat (ice) [J/kg/K]
Definition: scale_const.F90:67
real(rp), parameter, public const_dwatr
density of water [kg/m3]
Definition: scale_const.F90:82
real(rp), parameter, public const_cl
specific heat (liquid water) [J/kg/K]
Definition: scale_const.F90:66
integer, public io_fid_conf
Config file ID.
Definition: scale_io.F90:55
module file / external_input
subroutine, public file_external_input_regist(basename, varname, axistype, enable_periodic_year, enable_periodic_month, enable_periodic_day, step_fixed, offset, defval, check_coordinates, step_limit, exist)
Regist data.
real(rp), public const_undef
Definition: scale_const.F90:41
subroutine, public ocean_phy_ice_adjustment(OIA, OIS, OIE, OJA, OJS, OJE, calc_flag, OCEAN_DEPTH, OCEAN_TEMP, ICE_TEMP, ICE_MASS)
integer, parameter, public file_external_input_file_limit
limit of file (for one item)
module PROCESS
Definition: scale_prc.F90:11
subroutine, public prc_abort
Abort Process.
Definition: scale_prc.F90:338
module CONSTANT
Definition: scale_const.F90:11
real(rp), parameter, public const_emelt
Definition: scale_const.F90:72
subroutine, public ocean_phy_ice_fraction(OIA, OIS, OIE, OJA, OJS, OJE, ICE_MASS, ICE_FRAC)
module profiler
Definition: scale_prof.F90:11
module ocean / physics / ice / simple
module PRECISION
module CALENDAR
module STDIO
Definition: scale_io.F90:10
integer, parameter, public rp
subroutine, public ocean_phy_ice_simple(OIA, OIS, OIE, OJA, OJS, OJE, sflx_QV, sflx_rain, sflx_snow, sflx_hbalance, subsfc_temp, TC_dz, ICE_TEMP, ICE_MASS, calc_flag, dt, ICE_TEMP_t, ICE_MASS_t, sflx_G, sflx_water, sflx_ice)
Slab ocean model.