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: &
67  file_external_input_regist
68  implicit none
69 
70  real(dp) :: ocean_phy_ice_nudging_tau = 0.0_dp ! Relaxation time
71  character(len=H_SHORT) :: ocean_phy_ice_nudging_tau_unit = "SEC"
72  character(len=H_LONG) :: ocean_phy_ice_nudging_basename = ''
73  logical :: ocean_phy_ice_nudging_basename_add_num = .false.
74  integer :: ocean_phy_ice_nudging_number_of_files = 1
75  logical :: ocean_phy_ice_nudging_enable_periodic_year = .false.
76  logical :: ocean_phy_ice_nudging_enable_periodic_month = .false.
77  logical :: ocean_phy_ice_nudging_enable_periodic_day = .false.
78  integer :: ocean_phy_ice_nudging_step_fixed = 0
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_basename_add_num, &
94 ! OCEAN_PHY_ICE_nudging_number_of_files, &
95 ! OCEAN_PHY_ICE_nudging_enable_periodic_year, &
96 ! OCEAN_PHY_ICE_nudging_enable_periodic_month, &
97 ! OCEAN_PHY_ICE_nudging_enable_periodic_day, &
98 ! OCEAN_PHY_ICE_nudging_step_fixed, &
99 ! OCEAN_PHY_ICE_nudging_defval, &
100 ! OCEAN_PHY_ICE_nudging_check_coordinates, &
101 ! OCEAN_PHY_ICE_nudging_step_limit
102 
103  integer :: ierr
104  !---------------------------------------------------------------------------
105 
106  log_newline
107  log_info("OCEAN_PHY_ICE_setup",*) 'Setup'
108 
109  ocean_phy_ice_nudging_defval = undef
110 
111  !--- read namelist
112  rewind(io_fid_conf)
113  read(io_fid_conf,nml=param_ocean_phy_ice,iostat=ierr)
114  if( ierr < 0 ) then !--- missing
115  log_info("OCEAN_PHY_ICE_setup",*) 'Not found namelist. Default used.'
116  elseif( ierr > 0 ) then !--- fatal error
117  log_error("OCEAN_PHY_ICE_setup",*) 'Not appropriate names in namelist PARAM_OCEAN_PHY_ICE. Check!'
118  call prc_abort
119  endif
120  log_nml(param_ocean_phy_ice)
121 
122  log_newline
123  log_info("OCEAN_PHY_ICE_setup",*) 'Ice amount for frac. = 1 [kg/m2] : ', ocean_phy_ice_mass_critical
124  if ( ocean_phy_ice_nudging ) then
125  call calendar_unit2sec( ocean_phy_ice_nudging_tausec, ocean_phy_ice_nudging_tau, ocean_phy_ice_nudging_tau_unit )
126 
127  log_info("OCEAN_PHY_ICE_setup",*) 'Use nudging for sea ice fraction : ON'
128  log_info("OCEAN_PHY_ICE_setup",*) 'Relaxation time Tau [sec] : ', ocean_phy_ice_nudging_tausec
129 
130  if ( ocean_phy_ice_nudging_tausec == 0.0_rp ) then
131  ocean_phy_ice_offline_mode = .true.
132  log_info("OCEAN_PHY_ICE_setup",*) 'Tau=0 means that sea ice is completely replaced by the external data.'
133  endif
134 
135  if ( ocean_phy_ice_nudging_basename == '' ) then
136  log_error("OCEAN_PHY_ICE_setup",*) 'OCEAN_PHY_ICE_nudging_basename is necessary. STOP'
137  call prc_abort
138  endif
139  else
140  log_info("OCEAN_PHY_ICE_setup",*) 'Use nudging for sea ice fraction : OFF'
141  endif
142 
143  if ( ocean_phy_ice_nudging ) then
144  call file_external_input_regist( ocean_phy_ice_nudging_basename, & ! [IN]
145  ocean_phy_ice_nudging_basename_add_num, & ! [IN]
146  ocean_phy_ice_nudging_number_of_files, & ! [IN]
147  'OCEAN_ICE_FRAC', & ! [IN]
148  'XY', & ! [IN]
149  ocean_phy_ice_nudging_enable_periodic_year, & ! [IN]
150  ocean_phy_ice_nudging_enable_periodic_month, & ! [IN]
151  ocean_phy_ice_nudging_enable_periodic_day, & ! [IN]
152  ocean_phy_ice_nudging_step_fixed, & ! [IN]
153  ocean_phy_ice_nudging_defval, & ! [IN]
154  check_coordinates = ocean_phy_ice_nudging_check_coordinates, & ! [IN]
155  step_limit = ocean_phy_ice_nudging_step_limit ) ! [IN]
156  endif
157 
158  return
159  end subroutine ocean_phy_ice_setup
160 
161  !-----------------------------------------------------------------------------
162  subroutine ocean_phy_ice_fraction( &
163  OIA, OIS, OIE, &
164  OJA, OJS, OJE, &
165  ICE_MASS, &
166  ICE_FRAC )
167  implicit none
168 
169  integer, intent(in) :: oia, ois, oie
170  integer, intent(in) :: oja, ojs, oje
171  real(rp), intent(in) :: ice_mass(oia,oja) ! sea ice amount [kg/m2]
172  real(rp), intent(out) :: ice_frac(oia,oja) ! sea ice area fraction [1]
173 
174  integer :: i, j
175  !---------------------------------------------------------------------------
176  !$acc data copyin(ICE_MASS) copyout(ICE_FRAC)
177 
178  !$acc kernels
179  do j = ojs, oje
180  do i = ois, oie
181  ice_frac(i,j) = ice_mass(i,j) / ocean_phy_ice_mass_critical
182 
183  ice_frac(i,j) = min( sqrt( max( ice_frac(i,j), 0.0_rp ) ), ocean_phy_ice_fraction_limit )
184  enddo
185  enddo
186  !$acc end kernels
187 
188  !$acc end data
189  return
190  end subroutine ocean_phy_ice_fraction
191 
192  !-----------------------------------------------------------------------------
193  subroutine ocean_phy_ice_adjustment( &
194  OIA, OIS, OIE, &
195  OJA, OJS, OJE, &
196  calc_flag, &
197  OCEAN_DEPTH, &
198  OCEAN_TEMP, &
199  ICE_TEMP, &
200  ICE_MASS, &
201  MASS_FLUX, &
202  ENGI_FLUX, &
203  MASS_SUPL, &
204  ENGI_SUPL )
205  use scale_const, only: &
206  dwatr => const_dwatr, &
207  eps => const_eps
208  use scale_atmos_hydrometeor, only: &
209  cv_water, &
210  cv_ice, &
211  lhf
212  implicit none
213 
214  integer, intent(in) :: oia, ois, oie
215  integer, intent(in) :: oja, ojs, oje
216  logical, intent(in) :: calc_flag (oia,oja) ! to decide calculate or not
217  real(rp), intent(in) :: ocean_depth ! depth of the first layer of the ocean
218  real(rp), intent(inout) :: ocean_temp(oia,oja) ! ocean temperature [K]
219  real(rp), intent(inout) :: ice_temp (oia,oja) ! sea ice temperature [K]
220  real(rp), intent(inout) :: ice_mass (oia,oja) ! sea ice amount [kg/m2]
221  real(rp), intent(out) :: mass_flux(oia,oja)
222  real(rp), intent(out) :: engi_flux(oia,oja)
223  real(rp), intent(out) :: mass_supl (oia,oja)
224  real(rp), intent(out) :: engi_supl (oia,oja)
225 
226  real(rp) :: c_w
227  real(rp) :: ice_mass_frz
228  real(rp) :: ice_mass_prev
229 
230  integer :: i, j
231  !---------------------------------------------------------------------------
232  !$acc data copy(OCEAN_TEMP,ICE_TEMP,ICE_MASS) &
233  !$acc copyin(calc_flag) &
234  !$acc copyout(MASS_FLUX,ENGI_FLUX,MASS_SUPL,ENGI_SUPL)
235 
236  c_w = cv_water * dwatr * ocean_depth
237 
238  !$acc kernels
239  !$omp parallel do &
240  !$omp private(ICE_MASS_frz,ICE_MASS_prev)
241  do j = ojs, oje
242  do i = ois, oie
243  if ( calc_flag(i,j) &
244  .and. ocean_temp(i,j) < ocean_phy_ice_freezetemp .and. ice_mass(i,j) < ocean_phy_ice_mass_limit ) then
245  ice_mass_frz = c_w * ( ocean_phy_ice_freezetemp - ocean_temp(i,j) ) &
247  ice_mass_frz = min( ice_mass_frz, dwatr * ocean_depth )
248 
249  ! update ice mass
250  ice_mass_prev = ice_mass(i,j)
251  ice_mass(i,j) = ice_mass(i,j) + ice_mass_frz
252  ice_mass(i,j) = min( ice_mass(i,j), ocean_phy_ice_mass_limit ) ! apply limiter
253  ice_mass_frz = ice_mass(i,j) - ice_mass_prev
254 
255  ! update ice temperature
256  if ( ice_mass(i,j) > eps ) then
257  ice_temp(i,j) = ice_temp(i,j) &
258  + ( ocean_phy_ice_freezetemp - ice_temp(i,j) ) * ice_mass_frz / ice_mass(i,j)
259  else ! all ice melt
260  ice_temp(i,j) = ocean_phy_ice_freezetemp ! dummy
261  end if
262 
263  ! update ocean temperature
264  if ( c_w - cv_water * ice_mass_frz > eps ) then
265  ocean_temp(i,j) = ocean_temp(i,j) &
266  + ( cv_water * ocean_temp(i,j) - cv_ice * ocean_phy_ice_freezetemp + lhf ) * ice_mass_frz &
267  / ( c_w - cv_water * ice_mass_frz )
268  else ! all water freeze
269  ocean_temp(i,j) = ocean_phy_ice_freezetemp
270  end if
271 
272  mass_flux(i,j) = ice_mass_frz
273  engi_flux(i,j) = ( cv_ice * ocean_phy_ice_freezetemp - lhf ) * ice_mass_frz
274  mass_supl(i,j) = ice_mass_frz
275  engi_supl(i,j) = ice_mass_frz * cv_water * ocean_temp(i,j)
276  else
277  mass_flux(i,j) = 0.0_rp
278  engi_flux(i,j) = 0.0_rp
279  mass_supl(i,j) = 0.0_rp
280  engi_supl(i,j) = 0.0_rp
281  endif
282  enddo
283  enddo
284  !$acc end kernels
285 
286  !$acc end data
287  return
288  end subroutine ocean_phy_ice_adjustment
289 
290  !-----------------------------------------------------------------------------
292  subroutine ocean_phy_ice_simple( &
293  OIA, OIS, OIE, &
294  OJA, OJS, OJE, &
295  iflx_water, &
296  iflx_hbalance, &
297  subsfc_temp, &
298  TC_dz, &
299  ICE_TEMP, &
300  ICE_MASS, &
301  ICE_FRAC, &
302  calc_flag, &
303  dt, &
304  ICE_TEMP_t, &
305  ICE_MASS_t, &
306  sflx_G, &
307  sflx_water, &
308  sflx_RHOE )
309  use scale_prc, only: &
310  prc_abort
311  use scale_atmos_hydrometeor, only: &
312  cv_water, &
313  cv_ice, &
314  lhf
315  use scale_file_external_input, only: &
316  file_external_input_update
317  implicit none
318 
319  integer, intent(in) :: oia, ois, oie
320  integer, intent(in) :: oja, ojs, oje
321  real(rp), intent(in) :: iflx_water (oia,oja) ! input mass flux [kg/m2/s] (downward)
322  real(rp), intent(in) :: iflx_hbalance(oia,oja) ! input heat flux [J/m2/s] (downward)
323  real(rp), intent(in) :: subsfc_temp (oia,oja) ! subsurface temperature [K]
324  real(rp), intent(in) :: tc_dz (oia,oja) ! Thermal conductance [K/m]
325  real(rp), intent(in) :: ice_temp (oia,oja) ! sea ice temperature [K]
326  real(rp), intent(in) :: ice_mass (oia,oja) ! sea ice amount [kg/m2]
327  real(rp), intent(in) :: ice_frac (oia,oja) ! sea ice fraction [0-1]
328  logical, intent(in) :: calc_flag (oia,oja) ! to decide calculate or not
329  real(dp), intent(in) :: dt
330  real(rp), intent(out) :: ice_temp_t (oia,oja) ! tendency of sea ice temperature [K/s]
331  real(rp), intent(out) :: ice_mass_t (oia,oja) ! tendency of sea ice amount [kg/m2/s]
332  real(rp), intent(out) :: sflx_g (oia,oja) ! heat flux from sea ice to subsurface
333  real(rp), intent(out) :: sflx_water (oia,oja) ! mass flux from sea ice to subsurface
334  real(rp), intent(out) :: sflx_rhoe (oia,oja) ! internal energy flux from sea ice to subsurface
335 
336  real(rp) :: ice_mass_new ! [kg/m2]
337  real(rp) :: ice_temp_new ! [K]
338  real(rp) :: mass_budget ! [kg/m2/s]
339  real(rp) :: heat_budget ! [J/m2/s]
340  real(rp) :: g ! [J/m2/s]
341  real(rp) :: dm ! [kg/m2]
342  real(rp) :: de ! [J/m2]
343  real(rp) :: m_mlt ! [kg/m2]
344  real(rp) :: dt_rp
345 
346  integer :: i, j
347  !---------------------------------------------------------------------------
348  !$acc data copyin (iflx_water,iflx_hbalance,subsfc_temp, &
349  !$acc TC_dz,ICE_TEMP,ICE_MASS,ICE_FRAC,calc_flag) &
350  !$acc copyout(ICE_TEMP_t,ICE_MASS_t,SFLX_G,SFLX_water,SFLX_RHOE)
351 
352  log_progress(*) 'ocean / physics / seaice'
353 
354  dt_rp = real(dt,kind=rp)
355 
356  !$acc kernels
357  !$omp parallel do &
358  !$omp private(mass_budget,heat_budget,dM,dE,G,M_mlt, &
359  !$omp ICE_TEMP_new,ICE_MASS_new)
360  do j = ojs, oje
361  do i = ois, oie
362  if ( calc_flag(i,j) ) then
363 
364  ! mass change
365  dm = iflx_water(i,j) * ice_frac(i,j) * dt_rp
366  ice_mass_new = ice_mass(i,j) + dm
367 
368  if ( ice_mass_new > 0.0_rp ) then
369  ! internal energy change
370  g = ( subsfc_temp(i,j) - ice_temp(i,j) ) * tc_dz(i,j) ! heat flux from ocean
371  de = ( iflx_hbalance(i,j) + g ) * ice_frac(i,j) * dt_rp
372  ice_temp_new = ice_temp(i,j) &
373  + ( de - ( cv_ice * ice_temp(i,j) - lhf ) * dm ) / ( cv_ice * ice_mass_new )
374 
375  ! melting ice
376  m_mlt = cv_ice * ( ice_temp_new - ocean_phy_ice_freezetemp ) * ice_mass_new &
378  m_mlt = min( max( m_mlt, 0.0_rp ), ice_mass_new )
379 
380  ice_mass_new = ice_mass_new - m_mlt
381  ice_temp_new = ice_temp_new &
382  + ( cv_ice * ice_temp_new - lhf - cv_water * ocean_phy_ice_freezetemp ) * m_mlt &
383  / ( cv_ice * ice_mass_new )
384 
385  ! ice to ocean flux
386  mass_budget = m_mlt / dt_rp
387  sflx_rhoe(i,j) = cv_water * ocean_phy_ice_freezetemp * mass_budget
388  sflx_g(i,j) = - g * ice_frac(i,j)
389  sflx_water(i,j) = mass_budget
390 
391  else
392 
393  ice_mass_new = 0.0_rp
394  ice_temp_new = ocean_phy_ice_freezetemp ! dummy
395 
396  sflx_rhoe(i,j) = cv_water * subsfc_temp(i,j) * ice_mass_new / dt_rp
397  sflx_g(i,j) = ( cv_ice * ice_temp(i,j) - lhf ) * ice_mass(i,j) &
398  - sflx_rhoe(i,j) + iflx_hbalance(i,j) * ice_frac(i,j)
399  sflx_water(i,j) = ice_mass_new ! (negative)
400 
401  endif
402 
403  ice_mass_t(i,j) = ( ice_mass_new - ice_mass(i,j) ) / dt_rp
404  ice_temp_t(i,j) = ( ice_temp_new - ice_temp(i,j) ) / dt_rp
405 
406  else
407  sflx_g(i,j) = 0.0_rp
408  sflx_water(i,j) = 0.0_rp
409  sflx_rhoe(i,j) = 0.0_rp
410  ice_mass_t(i,j) = 0.0_rp
411  ice_temp_t(i,j) = 0.0_rp
412  endif
413  enddo
414  enddo
415  !$acc end kernels
416 
417  !$acc end data
418  return
419  end subroutine ocean_phy_ice_simple
420 
scale_prc::prc_abort
subroutine, public prc_abort
Abort Process.
Definition: scale_prc.F90:350
scale_ocean_phy_ice_simple::ocean_phy_ice_adjustment
subroutine, public ocean_phy_ice_adjustment(OIA, OIS, OIE, OJA, OJS, OJE, calc_flag, OCEAN_DEPTH, OCEAN_TEMP, ICE_TEMP, ICE_MASS, MASS_FLUX, ENGI_FLUX, MASS_SUPL, ENGI_SUPL)
Definition: scale_ocean_phy_ice_simple.F90:205
scale_ocean_phy_ice_simple
module ocean / physics / ice / simple
Definition: scale_ocean_phy_ice_simple.F90:12
scale_precision
module PRECISION
Definition: scale_precision.F90:14
scale_ocean_phy_ice_simple::ocean_phy_ice_density
real(rp), public ocean_phy_ice_density
Definition: scale_ocean_phy_ice_simple.F90:45
scale_const::const_eps
real(rp), public const_eps
small number
Definition: scale_const.F90:35
scale_atmos_hydrometeor
module atmosphere / hydrometeor
Definition: scale_atmos_hydrometeor.F90:12
scale_calendar
module CALENDAR
Definition: scale_calendar.F90:13
scale_prc
module PROCESS
Definition: scale_prc.F90:11
scale_precision::rp
integer, parameter, public rp
Definition: scale_precision.F90:41
scale_io
module STDIO
Definition: scale_io.F90:10
scale_const
module CONSTANT
Definition: scale_const.F90:11
scale_ocean_phy_ice_simple::ocean_phy_ice_freezetemp
real(rp), public ocean_phy_ice_freezetemp
Definition: scale_ocean_phy_ice_simple.F90:44
scale_prof
module profiler
Definition: scale_prof.F90:11
scale_precision::dp
integer, parameter, public dp
Definition: scale_precision.F90:32
scale_const::const_dwatr
real(rp), parameter, public const_dwatr
density of water [kg/m3]
Definition: scale_const.F90:89
scale_ocean_phy_ice_simple::ocean_phy_ice_simple
subroutine, public ocean_phy_ice_simple(OIA, OIS, OIE, OJA, OJS, OJE, iflx_water, iflx_hbalance, subsfc_temp, TC_dz, ICE_TEMP, ICE_MASS, ICE_FRAC, calc_flag, dt, ICE_TEMP_t, ICE_MASS_t, sflx_G, sflx_water, sflx_RHOE)
Slab ocean model.
Definition: scale_ocean_phy_ice_simple.F90:309
scale_ocean_phy_ice_simple::ocean_phy_ice_setup
subroutine, public ocean_phy_ice_setup
Definition: scale_ocean_phy_ice_simple.F90:60
scale_atmos_hydrometeor::lhf
real(rp), public lhf
latent heat of fusion for use [J/kg]
Definition: scale_atmos_hydrometeor.F90:146
scale_ocean_phy_ice_simple::ocean_phy_ice_fraction
subroutine, public ocean_phy_ice_fraction(OIA, OIS, OIE, OJA, OJS, OJE, ICE_MASS, ICE_FRAC)
Definition: scale_ocean_phy_ice_simple.F90:167
scale_file_external_input
module file / external_input
Definition: scale_file_external_input.F90:12
scale_const::const_undef
real(rp), public const_undef
Definition: scale_const.F90:43
scale_io::io_fid_conf
integer, public io_fid_conf
Config file ID.
Definition: scale_io.F90:57
scale_atmos_hydrometeor::cv_water
real(rp), public cv_water
CV for water [J/kg/K].
Definition: scale_atmos_hydrometeor.F90:151
scale_atmos_hydrometeor::cv_ice
real(rp), public cv_ice
CV for ice [J/kg/K].
Definition: scale_atmos_hydrometeor.F90:153
scale_calendar::calendar_unit2sec
subroutine, public calendar_unit2sec(second, value, unit)
Convert several units to second.
Definition: scale_calendar.F90:486