MOM6
ocean_model_MOM.F90
Go to the documentation of this file.
2 !***********************************************************************
3 !* GNU General Public License *
4 !* This file is a part of MOM. *
5 !* *
6 !* MOM is free software; you can redistribute it and/or modify it and *
7 !* are expected to follow the terms of the GNU General Public License *
8 !* as published by the Free Software Foundation; either version 2 of *
9 !* the License, or (at your option) any later version. *
10 !* *
11 !* MOM is distributed in the hope that it will be useful, but WITHOUT *
12 !* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
13 !* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public *
14 !* License for more details. *
15 !* *
16 !* For the full text of the GNU General Public License, *
17 !* write to: Free Software Foundation, Inc., *
18 !* 675 Mass Ave, Cambridge, MA 02139, USA. *
19 !* or see: http://www.gnu.org/licenses/gpl.html *
20 !***********************************************************************
21 
22 !-----------------------------------------------------------------------
23 !
24 ! This is the top level module for the MOM6 ocean model. It contains routines
25 ! for initialization, termination and update of ocean model state. This
26 ! particular version wraps all of the calls for MOM6 in the calls that had
27 ! been used for MOM4.
28 !
29 ! <CONTACT EMAIL="Robert.Hallberg@noaa.gov"> Robert Hallberg
30 ! </CONTACT>
31 !
32 !<OVERVIEW>
33 ! This code is a stop-gap wrapper of the MOM6 code to enable it to be called
34 ! in the same way as MOM4.
35 !</OVERVIEW>
36 
39 use mom, only : step_offline
40 use mom_constants, only : celsius_kelvin_offset, hlf
43 use mom_domains, only : pass_vector, agrid, bgrid_ne, cgrid_ne
44 use mom_error_handler, only : mom_error, fatal, warning, is_root_pe
49 use mom_grid, only : ocean_grid_type
50 use mom_io, only : close_file, file_exists, read_data, write_version_number
51 use mom_restart, only : save_restart
55 use mom_surface_forcing, only : surface_forcing_init, convert_iob_to_fluxes
56 use mom_surface_forcing, only : ice_ocn_bnd_type_chksum
57 use mom_surface_forcing, only : ice_ocean_boundary_type, surface_forcing_cs
59 use mom_time_manager, only : time_type, get_time, set_time, operator(>)
60 use mom_time_manager, only : operator(+), operator(-), operator(*), operator(/)
61 use mom_time_manager, only : operator(/=)
63 use mom_variables, only : surface
68 use mpp_domains_mod, only : domain2d, mpp_get_layout, mpp_get_global_domain
69 use mpp_domains_mod, only : mpp_define_domains, mpp_get_compute_domain, mpp_get_data_domain
72 use fms_mod, only : stdout
73 use mpp_mod, only : mpp_chksum
74 use mom_domains, only : pass_var, pass_vector, to_all, cgrid_ne, bgrid_ne
75 use mom_eos, only : gsw_sp_from_sr, gsw_pt_from_ct
76 
77 #include <MOM_memory.h>
78 
79 #ifdef _USE_GENERIC_TRACER
80 use mom_generic_tracer, only : mom_generic_flux_init,mom_generic_tracer_fluxes_accumulate
81 #endif
82 
83 implicit none ; private
84 
87 public ice_ocean_boundary_type
90 public ice_ocn_bnd_type_chksum
94  module procedure ocean_model_data1d_get
95  module procedure ocean_model_data2d_get
96 end interface
97 
98 
99 ! This type is used for communication with other components via the FMS coupler.
100 ! The element names and types can be changed only with great deliberation, hence
101 ! the persistnce of things like the cutsy element name "avg_kount".
102 type, public :: ocean_public_type
103  type(domain2d) :: domain ! The domain for the surface fields.
104  logical :: is_ocean_pe ! .true. on processors that run the ocean model.
105  character(len=32) :: instance_name = '' ! A name that can be used to identify
106  ! this instance of an ocean model, for example
107  ! in ensembles when writing messages.
108  integer, pointer, dimension(:) :: pelist => null() ! The list of ocean PEs.
109  logical, pointer, dimension(:,:) :: maskmap =>null() ! A pointer to an array
110  ! indicating which logical processors are actually used for
111  ! the ocean code. The other logical processors would be all
112  ! land points and are not assigned to actual processors.
113  ! This need not be assigned if all logical processors are used.
114 
115  integer :: stagger = -999 ! The staggering relative to the tracer points
116  ! points of the two velocity components. Valid entries
117  ! include AGRID, BGRID_NE, CGRID_NE, BGRID_SW, and CGRID_SW,
118  ! corresponding to the community-standard Arakawa notation.
119  ! (These are named integers taken from mpp_parameter_mod.)
120  ! Following MOM, this is BGRID_NE by default when the ocean
121  ! is initialized, but here it is set to -999 so that a
122  ! global max across ocean and non-ocean processors can be
123  ! used to determine its value.
124  real, pointer, dimension(:,:) :: &
125  t_surf => null(), & ! SST on t-cell (degrees Kelvin)
126  s_surf => null(), & ! SSS on t-cell (psu)
127  u_surf => null(), & ! i-velocity at the locations indicated by stagger, m/s.
128  v_surf => null(), & ! j-velocity at the locations indicated by stagger, m/s.
129  sea_lev => null(), & ! Sea level in m after correction for surface pressure,
130  ! i.e. dzt(1) + eta_t + patm/rho0/grav (m)
131  frazil =>null(), & ! Accumulated heating (in Joules/m^2) from frazil
132  ! formation in the ocean.
133  area => null() ! cell area of the ocean surface, in m2.
134  type(coupler_2d_bc_type) :: fields ! A structure that may contain an
135  ! array of named tracer-related fields.
136  integer :: avg_kount ! Used for accumulating averages of this type.
137  integer, dimension(2) :: axes = 0 ! Axis numbers that are available
138  ! for I/O using this surface data.
139 end type ocean_public_type
140 
141 
142 type, public :: ocean_state_type ; private
143  ! This type is private, and can therefore vary between different ocean models.
144  ! All information entire ocean state may be contained here, although it is not
145  ! necessary that this is implemented with all models.
146  logical :: is_ocean_pe = .false. ! True if this is an ocean PE.
147  type(time_type) :: time ! The ocean model's time and master clock.
148  integer :: restart_control ! An integer that is bit-tested to determine whether
149  ! incremental restart files are saved and whether they
150  ! have a time stamped name. +1 (bit 0) for generic
151  ! files and +2 (bit 1) for time-stamped files. A
152  ! restart file is saved at the end of a run segment
153  ! unless Restart_control is negative.
154  type(time_type) :: energysavedays ! The interval between writing the energies
155  ! and other integral quantities of the run.
156  type(time_type) :: write_energy_time ! The next time to write to the energy file.
157 
158  integer :: nstep = 0 ! The number of calls to update_ocean.
159  logical :: use_ice_shelf ! If true, the ice shelf model is enabled.
160  logical :: icebergs_apply_rigid_boundary ! If true, the icebergs can change ocean bd condition.
161  real :: kv_iceberg ! The viscosity of the icebergs in m2/s (for ice rigidity)
162  real :: berg_area_threshold ! Fraction of grid cell which iceberg must occupy
163  !so that fluxes below are set to zero. (0.5 is a
164  !good value to use. Not applied for negative values.
165  real :: latent_heat_fusion ! Latent heat of fusion
166  real :: density_iceberg ! A typical density of icebergs in kg/m3 (for ice rigidity)
167  type(ice_shelf_cs), pointer :: ice_shelf_csp => null()
168  logical :: restore_salinity ! If true, the coupled MOM driver adds a term to
169  ! restore salinity to a specified value.
170  logical :: restore_temp ! If true, the coupled MOM driver adds a term to
171  ! restore sst to a specified value.
172  real :: press_to_z ! A conversion factor between pressure and ocean
173  ! depth in m, usually 1/(rho_0*g), in m Pa-1.
174  real :: c_p ! The heat capacity of seawater, in J K-1 kg-1.
175 
176  type(directories) :: dirs ! A structure containing several relevant directory paths.
177  type(forcing) :: fluxes ! A structure containing pointers to
178  ! the ocean forcing fields.
179  type(forcing) :: flux_tmp ! A secondary structure containing pointers to the
180  ! ocean forcing fields for when multiple coupled
181  ! timesteps are taken per thermodynamic step.
182  type(surface) :: state ! A structure containing pointers to
183  ! the ocean surface state fields.
184  type(ocean_grid_type), pointer :: grid => null() ! A pointer to a grid structure
185  ! containing metrics and related information.
186  type(verticalgrid_type), pointer :: gv => null() ! A pointer to a vertical grid
187  ! structure containing metrics and related information.
188  type(mom_control_struct), pointer :: mom_csp => null()
189  type(surface_forcing_cs), pointer :: forcing_csp => null()
190  type(sum_output_cs), pointer :: sum_output_csp => null()
191 end type ocean_state_type
192 
193 contains
194 
195 !=======================================================================
196 ! <SUBROUTINE NAME="ocean_model_init">
197 !
198 ! <DESCRIPTION>
199 ! Initialize the ocean model.
200 ! </DESCRIPTION>
201 !
202 subroutine ocean_model_init(Ocean_sfc, OS, Time_init, Time_in)
203  type(ocean_public_type), target, intent(inout) :: Ocean_sfc
204  type(ocean_state_type), pointer :: OS
205  type(time_type), intent(in) :: Time_init
206  type(time_type), intent(in) :: Time_in
207 ! This subroutine initializes both the ocean state and the ocean surface type.
208 ! Because of the way that indicies and domains are handled, Ocean_sfc must have
209 ! been used in a previous call to initialize_ocean_type.
210 
211 ! Arguments: Ocean_sfc - A structure containing various publicly visible ocean
212 ! surface properties after initialization, this is intent(out).
213 ! (out,private) OS - A structure whose internal contents are private
214 ! to ocean_model_mod that may be used to contain all
215 ! information about the ocean's interior state.
216 ! (in) Time_init - The start time for the coupled model's calendar.
217 ! (in) Time_in - The time at which to initialize the ocean model.
218  real :: Time_unit ! The time unit in seconds for ENERGYSAVEDAYS.
219  real :: Rho0 ! The Boussinesq ocean density, in kg m-3.
220  real :: G_Earth ! The gravitational acceleration in m s-2.
221 ! This include declares and sets the variable "version".
222 #include "version_variable.h"
223  character(len=40) :: mdl = "ocean_model_init" ! This module's name.
224  character(len=48) :: stagger
225  integer :: secs, days
226  type(param_file_type) :: param_file !< A structure to parse for run-time parameters
227  logical :: offline_tracer_mode
228 
229  call calltree_enter("ocean_model_init(), ocean_model_MOM.F90")
230  if (associated(os)) then
231  call mom_error(warning, "ocean_model_init called with an associated "// &
232  "ocean_state_type structure. Model is already initialized.")
233  return
234  endif
235  allocate(os)
236 
237  os%is_ocean_pe = ocean_sfc%is_ocean_pe
238  if (.not.os%is_ocean_pe) return
239 
240  os%state%tr_fields => ocean_sfc%fields
241  os%Time = time_in
242  call initialize_mom(os%Time, param_file, os%dirs, os%MOM_CSp, time_in, &
243  offline_tracer_mode=offline_tracer_mode)
244  os%grid => os%MOM_CSp%G ; os%GV => os%MOM_CSp%GV
245  os%C_p = os%MOM_CSp%tv%C_p
246  os%fluxes%C_p = os%MOM_CSp%tv%C_p
247 
248  ! Read all relevant parameters and write them to the model log.
249  call log_version(param_file, mdl, version, "")
250  call get_param(param_file, mdl, "RESTART_CONTROL", os%Restart_control, &
251  "An integer whose bits encode which restart files are \n"//&
252  "written. Add 2 (bit 1) for a time-stamped file, and odd \n"//&
253  "(bit 0) for a non-time-stamped file. A restart file \n"//&
254  "will be saved at the end of the run segment for any \n"//&
255  "non-negative value.", default=1)
256  call get_param(param_file, mdl, "TIMEUNIT", time_unit, &
257  "The time unit for ENERGYSAVEDAYS.", &
258  units="s", default=86400.0)
259  call get_param(param_file, mdl, "ENERGYSAVEDAYS",os%energysavedays, &
260  "The interval in units of TIMEUNIT between saves of the \n"//&
261  "energies of the run and other globally summed diagnostics.", &
262  default=set_time(0,days=1), timeunit=time_unit)
263 
264  call get_param(param_file, mdl, "OCEAN_SURFACE_STAGGER", stagger, &
265  "A case-insensitive character string to indicate the \n"//&
266  "staggering of the surface velocity field that is \n"//&
267  "returned to the coupler. Valid values include \n"//&
268  "'A', 'B', or 'C'.", default="C")
269  if (uppercase(stagger(1:1)) == 'A') then ; ocean_sfc%stagger = agrid
270  elseif (uppercase(stagger(1:1)) == 'B') then ; ocean_sfc%stagger = bgrid_ne
271  elseif (uppercase(stagger(1:1)) == 'C') then ; ocean_sfc%stagger = cgrid_ne
272  else ; call mom_error(fatal,"ocean_model_init: OCEAN_SURFACE_STAGGER = "// &
273  trim(stagger)//" is invalid.") ; endif
274 
275  call get_param(param_file, mdl, "RESTORE_SALINITY",os%restore_salinity, &
276  "If true, the coupled driver will add a globally-balanced \n"//&
277  "fresh-water flux that drives sea-surface salinity \n"//&
278  "toward specified values.", default=.false.)
279  call get_param(param_file, mdl, "RESTORE_TEMPERATURE",os%restore_temp, &
280  "If true, the coupled driver will add a \n"//&
281  "heat flux that drives sea-surface temperauture \n"//&
282  "toward specified values.", default=.false.)
283  call get_param(param_file, mdl, "RHO_0", rho0, &
284  "The mean ocean density used with BOUSSINESQ true to \n"//&
285  "calculate accelerations and the mass for conservation \n"//&
286  "properties, or with BOUSSINSEQ false to convert some \n"//&
287  "parameters from vertical units of m to kg m-2.", &
288  units="kg m-3", default=1035.0)
289  call get_param(param_file, mdl, "G_EARTH", g_earth, &
290  "The gravitational acceleration of the Earth.", &
291  units="m s-2", default = 9.80)
292 
293  call get_param(param_file, mdl, "ICE_SHELF", os%use_ice_shelf, &
294  "If true, enables the ice shelf model.", default=.false.)
295 
296  call get_param(param_file, mdl, "ICEBERGS_APPLY_RIGID_BOUNDARY", os%icebergs_apply_rigid_boundary, &
297  "If true, allows icebergs to change boundary condition felt by ocean", default=.false.)
298 
299  if (os%icebergs_apply_rigid_boundary) then
300  call get_param(param_file, mdl, "KV_ICEBERG", os%kv_iceberg, &
301  "The viscosity of the icebergs", units="m2 s-1",default=1.0e10)
302  call get_param(param_file, mdl, "DENSITY_ICEBERGS", os%density_iceberg, &
303  "A typical density of icebergs.", units="kg m-3", default=917.0)
304  call get_param(param_file, mdl, "LATENT_HEAT_FUSION", os%latent_heat_fusion, &
305  "The latent heat of fusion.", units="J/kg", default=hlf)
306  call get_param(param_file, mdl, "BERG_AREA_THRESHOLD", os%berg_area_threshold, &
307  "Fraction of grid cell which iceberg must occupy, so that fluxes \n"//&
308  "below berg are set to zero. Not applied for negative \n"//&
309  " values.", units="non-dim", default=-1.0)
310  endif
311 
312  os%press_to_z = 1.0/(rho0*g_earth)
313 
314  call surface_forcing_init(time_in, os%grid, param_file, os%MOM_CSp%diag, &
315  os%forcing_CSp, os%restore_salinity, os%restore_temp)
316 
317  if (os%use_ice_shelf) then
318  call initialize_ice_shelf(param_file, os%grid, os%Time, os%ice_shelf_CSp, &
319  os%MOM_CSp%diag, os%fluxes)
320  endif
321  if (os%icebergs_apply_rigid_boundary) then
322  !call allocate_forcing_type(OS%grid, OS%fluxes, iceberg=.true.)
323  !This assumes that the iceshelf and ocean are on the same grid. I hope this is true
324  if (.not. os%use_ice_shelf) call allocate_forcing_type(os%grid, os%fluxes, ustar=.true., shelf=.true.)
325  endif
326 
327  call mom_sum_output_init(os%grid, param_file, os%dirs%output_directory, &
328  os%MOM_CSp%ntrunc, time_init, os%sum_output_CSp)
329 
330  ! This call has been moved into the first call to update_ocean_model.
331 ! call write_energy(OS%MOM_CSp%u, OS%MOM_CSp%v, OS%MOM_CSp%h, OS%MOM_CSp%tv, &
332 ! OS%Time, 0, OS%grid, OS%GV, OS%sum_output_CSp, OS%MOM_CSp%tracer_flow_CSp)
333 
334  ! write_energy_time is the next integral multiple of energysavedays.
335  os%write_energy_time = time_init + os%energysavedays * &
336  (1 + (os%Time - time_init) / os%energysavedays)
337 
338  if(ASSOCIATED(os%grid%Domain%maskmap)) then
339  call initialize_ocean_public_type(os%grid%Domain%mpp_domain, ocean_sfc, &
340  os%MOM_CSp%diag, maskmap=os%grid%Domain%maskmap)
341  else
342  call initialize_ocean_public_type(os%grid%Domain%mpp_domain, ocean_sfc, &
343  os%MOM_CSp%diag)
344  endif
345 ! call convert_state_to_ocean_type(state, Ocean_sfc, OS%grid)
346 
347  call close_param_file(param_file)
348  call diag_mediator_close_registration(os%MOM_CSp%diag)
349 
350  if (is_root_pe()) &
351  write(*,'(/12x,a/)') '======== COMPLETED MOM INITIALIZATION ========'
352 
353  call calltree_leave("ocean_model_init(")
354 end subroutine ocean_model_init
355 ! </SUBROUTINE> NAME="ocean_model_init"
356 
357 
358 !=======================================================================
359 ! <SUBROUTINE NAME="update_ocean_model">
360 !
361 ! <DESCRIPTION>
362 ! Update in time the ocean model fields. This code wraps the call to step_MOM
363 ! with MOM4's call.
364 ! </DESCRIPTION>
365 !
366 
367 subroutine update_ocean_model(Ice_ocean_boundary, OS, Ocean_sfc, &
368  time_start_update, Ocean_coupling_time_step)
369  type(ice_ocean_boundary_type), intent(inout) :: Ice_ocean_boundary
370  type(ocean_state_type), pointer :: OS
371  type(ocean_public_type), intent(inout) :: Ocean_sfc
372  type(time_type), intent(in) :: time_start_update
373  type(time_type), intent(in) :: Ocean_coupling_time_step
374 ! This subroutine uses the forcing in Ice_ocean_boundary to advance the
375 ! ocean model's state from the input value of Ocean_state (which must be for
376 ! time time_start_update) for a time interval of Ocean_coupling_time_step,
377 ! returning the publicly visible ocean surface properties in Ocean_sfc and
378 ! storing the new ocean properties in Ocean_state.
379 
380 ! Arguments: Ice_ocean_boundary - A structure containing the various forcing
381 ! fields coming from the ice. It is intent in.
382 ! (inout) Ocean_state - A structure containing the internal ocean state.
383 ! (out) Ocean_sfc - A structure containing all the publicly visible ocean
384 ! surface fields after a coupling time step.
385 ! (in) time_start_update - The time at the beginning of the update step.
386 ! (in) Ocean_coupling_time_step - The amount of time over which to advance
387 ! the ocean.
388 
389 ! Note: although several types are declared intent(inout), this is to allow for
390 ! the possibility of halo updates and to keep previously allocated memory.
391 ! In practice, Ice_ocean_boundary is intent in, Ocean_state is private to
392 ! this module and intent inout, and Ocean_sfc is intent out.
393  type(time_type) :: Master_time ! This allows step_MOM to temporarily change
394  ! the time that is seen by internal modules.
395  type(time_type) :: Time1 ! The value of the ocean model's time at the
396  ! start of a call to step_MOM.
397  integer :: index_bnds(4) ! The computational domain index bounds in the
398  ! ice-ocean boundary type.
399  real :: weight ! Flux accumulation weight
400  real :: time_step ! The time step of a call to step_MOM in seconds.
401  integer :: secs, days
402 
403  call calltree_enter("update_ocean_model(), ocean_model_MOM.F90")
404  call get_time(ocean_coupling_time_step, secs, days)
405  time_step = 86400.0*real(days) + real(secs)
406 
407  if (time_start_update /= os%Time) then
408  call mom_error(warning, "update_ocean_model: internal clock does not "//&
409  "agree with time_start_update argument.")
410  endif
411  if (.not.associated(os)) then
412  call mom_error(fatal, "update_ocean_model called with an unassociated "// &
413  "ocean_state_type structure. ocean_model_init must be "// &
414  "called first to allocate this structure.")
415  return
416  endif
417 
418 ! Translate Ice_ocean_boundary into fluxes.
419  call mpp_get_compute_domain(ocean_sfc%Domain, index_bnds(1), index_bnds(2), &
420  index_bnds(3), index_bnds(4))
421 
422  weight = 1.0
423 
424  if (os%fluxes%fluxes_used) then
425  call enable_averaging(time_step, os%Time + ocean_coupling_time_step, os%MOM_CSp%diag) ! Needed to allow diagnostics in convert_IOB
426  call convert_iob_to_fluxes(ice_ocean_boundary, os%fluxes, index_bnds, os%Time, &
427  os%grid, os%forcing_CSp, os%state, os%restore_salinity,os%restore_temp)
428 #ifdef _USE_GENERIC_TRACER
429  call mom_generic_tracer_fluxes_accumulate(os%fluxes, weight) !here weight=1, just saving the current fluxes
430 #endif
431 
432  ! Add ice shelf fluxes
433  if (os%use_ice_shelf) then
434  call shelf_calc_flux(os%State, os%fluxes, os%Time, time_step, os%Ice_shelf_CSp)
435  endif
436  if (os%icebergs_apply_rigid_boundary) then
437  !This assumes that the iceshelf and ocean are on the same grid. I hope this is true
438  call add_berg_flux_to_shelf(os%grid, os%fluxes,os%use_ice_shelf,os%density_iceberg,os%kv_iceberg, os%latent_heat_fusion, os%State, time_step, os%berg_area_threshold)
439  endif
440  ! Indicate that there are new unused fluxes.
441  os%fluxes%fluxes_used = .false.
442  os%fluxes%dt_buoy_accum = time_step
443  else
444  os%flux_tmp%C_p = os%fluxes%C_p
445  call convert_iob_to_fluxes(ice_ocean_boundary, os%flux_tmp, index_bnds, os%Time, &
446  os%grid, os%forcing_CSp, os%state, os%restore_salinity,os%restore_temp)
447  if (os%use_ice_shelf) then
448  call shelf_calc_flux(os%State, os%flux_tmp, os%Time, time_step, os%Ice_shelf_CSp)
449  endif
450  if (os%icebergs_apply_rigid_boundary) then
451  !This assumes that the iceshelf and ocean are on the same grid. I hope this is true
452  call add_berg_flux_to_shelf(os%grid, os%flux_tmp, os%use_ice_shelf,os%density_iceberg,os%kv_iceberg, os%latent_heat_fusion, os%State, time_step, os%berg_area_threshold)
453  endif
454 
455  call forcing_accumulate(os%flux_tmp, os%fluxes, time_step, os%grid, weight)
456 #ifdef _USE_GENERIC_TRACER
457  call mom_generic_tracer_fluxes_accumulate(os%flux_tmp, weight) !weight of the current flux in the running average
458 #endif
459  endif
460 
461  if (os%nstep==0) then
462  call finish_mom_initialization(os%Time, os%dirs, os%MOM_CSp, os%fluxes)
463 
464  call write_energy(os%MOM_CSp%u, os%MOM_CSp%v, os%MOM_CSp%h, os%MOM_CSp%tv, &
465  os%Time, 0, os%grid, os%GV, os%sum_output_CSp, &
466  os%MOM_CSp%tracer_flow_CSp)
467  endif
468 
469  call disable_averaging(os%MOM_CSp%diag)
470  master_time = os%Time ; time1 = os%Time
471 
472  if(os%MOM_Csp%offline_tracer_mode) then
473  call step_offline(os%fluxes, os%state, time1, time_step, os%MOM_CSp)
474  else
475  call step_mom(os%fluxes, os%state, time1, time_step, os%MOM_CSp)
476  endif
477 
478  os%Time = master_time + ocean_coupling_time_step
479  os%nstep = os%nstep + 1
480 
481  call enable_averaging(time_step, os%Time, os%MOM_CSp%diag)
482  call mech_forcing_diags(os%fluxes, time_step, os%grid, &
483  os%MOM_CSp%diag, os%forcing_CSp%handles)
484  call disable_averaging(os%MOM_CSp%diag)
485 
486  if (os%fluxes%fluxes_used) then
487  call enable_averaging(os%fluxes%dt_buoy_accum, os%Time, os%MOM_CSp%diag)
488  call forcing_diagnostics(os%fluxes, os%state, os%fluxes%dt_buoy_accum, &
489  os%grid, os%MOM_CSp%diag, os%forcing_CSp%handles)
490  call accumulate_net_input(os%fluxes, os%state, os%fluxes%dt_buoy_accum, &
491  os%grid, os%sum_output_CSp)
492  call disable_averaging(os%MOM_CSp%diag)
493  endif
494 
495 ! See if it is time to write out the energy.
496  if ((os%Time + ((ocean_coupling_time_step)/2) > os%write_energy_time) .and. &
497  (os%MOM_CSp%t_dyn_rel_adv==0.0)) then
498  call write_energy(os%MOM_CSp%u, os%MOM_CSp%v, os%MOM_CSp%h, os%MOM_CSp%tv, &
499  os%Time, os%nstep, os%grid, os%GV, os%sum_output_CSp, &
500  os%MOM_CSp%tracer_flow_CSp)
501  os%write_energy_time = os%write_energy_time + os%energysavedays
502  endif
503 
504 ! Translate state into Ocean.
505 ! call convert_state_to_ocean_type(OS%state, Ocean_sfc, OS%grid, &
506 ! Ice_ocean_boundary%p, OS%press_to_z)
507  call convert_state_to_ocean_type(os%state, ocean_sfc, os%grid, os%MOM_CSp%use_conT_absS)
508 
509  call calltree_leave("update_ocean_model()")
510 end subroutine update_ocean_model
511 ! </SUBROUTINE> NAME="update_ocean_model"
512 
513 !=======================================================================
514 ! <SUBROUTINE NAME="ocean_model_restart">
515 !
516 ! <DESCRIPTION>
517 ! write out restart file.
518 ! Arguments:
519 ! timestamp (optional, intent(in)) : A character string that represents the model time,
520 ! used for writing restart. timestamp will append to
521 ! the any restart file name as a prefix.
522 ! </DESCRIPTION>
523 !
524 
525 subroutine add_berg_flux_to_shelf(G, fluxes, use_ice_shelf, density_ice, kv_ice, latent_heat_fusion, state, time_step, berg_area_threshold)
526  type(ocean_grid_type), intent(inout) :: G !< The ocean's grid structure
527  type(forcing), intent(inout) :: fluxes
528  type(surface), intent(inout) :: state
529  logical, intent(in) :: use_ice_shelf
530  real, intent(in) :: kv_ice ! The viscosity of ice, in m2 s-1.
531  real, intent(in) :: density_ice ! A typical density of ice, in kg m-3.
532  real, intent(in) :: latent_heat_fusion ! The latent heat of fusion, in J kg-1.
533  real, intent(in) :: time_step ! The latent heat of fusion, in J kg-1.
534  real, intent(in) :: berg_area_threshold !Area threshold for zero'ing fluxes bellow iceberg
535 ! Arguments:
536 ! (in) fluxes - A structure of surface fluxes that may be used.
537 ! (in) G - The ocean's grid structure.
538  real :: fraz ! refreezing rate in kg m-2 s-1
539  integer :: i, j, is, ie, js, je, isd, ied, jsd, jed
540  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
541  isd = g%isd ; jsd = g%jsd ; ied = g%ied ; jed = g%jed
542  !This routine adds iceberg data to the ice shelf data (if ice shelf is used)
543  !which can then be used to change the top of ocean boundary condition used in
544  !the ocean model. This routine is taken from the add_shelf_flux subroutine
545  !within the ice shelf model.
546 
547  if (.not. (((associated(fluxes%frac_shelf_h) .and. associated(fluxes%frac_shelf_u)) &
548  .and.(associated(fluxes%frac_shelf_v) .and. associated(fluxes%ustar_shelf)))&
549  .and.(associated(fluxes%rigidity_ice_u) .and. associated(fluxes%rigidity_ice_v)))) return
550 
551  if (.not. ((associated(fluxes%area_berg) .and. associated(fluxes%ustar_berg)) .and. associated(fluxes%mass_berg) ) ) return
552 
553  if (.not. use_ice_shelf) then
554  fluxes%frac_shelf_h(:,:)=0.
555  fluxes%frac_shelf_u(:,:)=0.
556  fluxes%frac_shelf_v(:,:)=0.
557  fluxes%ustar_shelf(:,:)=0.
558  fluxes%rigidity_ice_u(:,:)=0.
559  fluxes%rigidity_ice_v(:,:)=0.
560  endif
561 
562  do j=jsd,jed ; do i=isd,ied
563  if (g%areaT(i,j) > 0.0) &
564  fluxes%frac_shelf_h(i,j) = fluxes%frac_shelf_h(i,j) + fluxes%area_berg(i,j)
565  fluxes%ustar_shelf(i,j) = fluxes%ustar_shelf(i,j) + fluxes%ustar_berg(i,j)
566  enddo ; enddo
567  !do I=isd,ied-1 ; do j=isd,jed
568  do j=jsd,jed ; do i=isd,ied-1 ! ### changed stride order; i->ied-1?
569  fluxes%frac_shelf_u(i,j) = 0.0
570  if ((g%areaT(i,j) + g%areaT(i+1,j) > 0.0)) & ! .and. (G%dxdy_u(I,j) > 0.0)) &
571  fluxes%frac_shelf_u(i,j) = fluxes%frac_shelf_u(i,j) + (((fluxes%area_berg(i,j)*g%areaT(i,j)) + (fluxes%area_berg(i+1,j)*g%areaT(i+1,j))) / &
572  (g%areaT(i,j) + g%areaT(i+1,j)))
573  fluxes%rigidity_ice_u(i,j) = fluxes%rigidity_ice_u(i,j) +((kv_ice / density_ice) * &
574  min(fluxes%mass_berg(i,j), fluxes%mass_berg(i+1,j)))
575  enddo ; enddo
576  do j=jsd,jed-1 ; do i=isd,ied ! ### change stride order; j->jed-1?
577  !do i=isd,ied ; do J=isd,jed-1
578  fluxes%frac_shelf_v(i,j) = 0.0
579  if ((g%areaT(i,j) + g%areaT(i,j+1) > 0.0)) & ! .and. (G%dxdy_v(i,J) > 0.0)) &
580  fluxes%frac_shelf_v(i,j) = fluxes%frac_shelf_v(i,j) + (((fluxes%area_berg(i,j)*g%areaT(i,j)) + (fluxes%area_berg(i,j+1)*g%areaT(i,j+1))) / &
581  (g%areaT(i,j) + g%areaT(i,j+1) ))
582  fluxes%rigidity_ice_v(i,j) = fluxes%rigidity_ice_v(i,j) +((kv_ice / density_ice) * &
583  max(fluxes%mass_berg(i,j), fluxes%mass_berg(i,j+1)))
584  enddo ; enddo
585  call pass_vector(fluxes%frac_shelf_u, fluxes%frac_shelf_v, g%domain, to_all, cgrid_ne)
586 
587  !Zero'ing out other fluxes under the tabular icebergs
588  if (berg_area_threshold >= 0.) then
589  do j=jsd,jed ; do i=isd,ied
590  if (fluxes%frac_shelf_h(i,j) > berg_area_threshold) then !Only applying for ice shelf covering most of cell
591 
592  if (associated(fluxes%sw)) fluxes%sw(i,j) = 0.0
593  if (associated(fluxes%lw)) fluxes%lw(i,j) = 0.0
594  if (associated(fluxes%latent)) fluxes%latent(i,j) = 0.0
595  if (associated(fluxes%evap)) fluxes%evap(i,j) = 0.0
596 
597  ! Add frazil formation diagnosed by the ocean model (J m-2) in the
598  ! form of surface layer evaporation (kg m-2 s-1). Update lprec in the
599  ! control structure for diagnostic purposes.
600 
601  if (associated(state%frazil)) then
602  fraz = state%frazil(i,j) / time_step / latent_heat_fusion
603  if (associated(fluxes%evap)) fluxes%evap(i,j) = fluxes%evap(i,j) - fraz
604  !CS%lprec(i,j)=CS%lprec(i,j) - fraz
605  state%frazil(i,j) = 0.0
606  endif
607 
608  !Alon: Should these be set to zero too?
609  if (associated(fluxes%sens)) fluxes%sens(i,j) = 0.0
610  if (associated(fluxes%salt_flux)) fluxes%salt_flux(i,j) = 0.0
611  if (associated(fluxes%lprec)) fluxes%lprec(i,j) = 0.0
612  endif
613  enddo ; enddo
614  endif
615 
616 end subroutine add_berg_flux_to_shelf
617 
618 subroutine ocean_model_restart(OS, timestamp)
619  type(ocean_state_type), pointer :: OS
620  character(len=*), intent(in), optional :: timestamp
621 
622  if (os%MOM_CSp%t_dyn_rel_adv > 0.0) call mom_error(warning, "End of MOM_main reached "//&
623  "with inconsistent dynamics and advective times. Additional restart fields "//&
624  "that have not been coded yet would be required for reproducibility.")
625  if (.not.os%fluxes%fluxes_used) call mom_error(fatal, "ocean_model_restart "//&
626  "was called with unused buoyancy fluxes. For conservation, the ocean "//&
627  "restart files can only be created after the buoyancy forcing is applied.")
628 
629  if (btest(os%Restart_control,1)) then
630  call save_restart(os%dirs%restart_output_dir, os%Time, os%grid, &
631  os%MOM_CSp%restart_CSp, .true., gv=os%GV)
632  call forcing_save_restart(os%forcing_CSp, os%grid, os%Time, &
633  os%dirs%restart_output_dir, .true.)
634  if (os%use_ice_shelf) then
635  call ice_shelf_save_restart(os%Ice_shelf_CSp, os%Time, os%dirs%restart_output_dir, .true.)
636  endif
637  endif
638  if (btest(os%Restart_control,0)) then
639  call save_restart(os%dirs%restart_output_dir, os%Time, os%grid, &
640  os%MOM_CSp%restart_CSp, gv=os%GV)
641  call forcing_save_restart(os%forcing_CSp, os%grid, os%Time, &
642  os%dirs%restart_output_dir)
643  if (os%use_ice_shelf) then
644  call ice_shelf_save_restart(os%Ice_shelf_CSp, os%Time, os%dirs%restart_output_dir)
645  endif
646  endif
647 
648 end subroutine ocean_model_restart
649 ! </SUBROUTINE> NAME="ocean_model_restart"
650 
651 !=======================================================================
652 ! <SUBROUTINE NAME="ocean_model_end">
653 !
654 ! <DESCRIPTION>
655 ! Close down the ocean model
656 ! </DESCRIPTION>
657 !
658 subroutine ocean_model_end(Ocean_sfc, Ocean_state, Time)
659  type(ocean_public_type), intent(inout) :: Ocean_sfc
660  type(ocean_state_type), pointer :: Ocean_state
661  type(time_type), intent(in) :: Time
662 
663 ! This subroutine terminates the model run, saving the ocean state in a
664 ! restart file and deallocating any data associated with the ocean.
665 
666 ! Arguments: Ocean_sfc - An ocean_public_type structure that is to be
667 ! deallocated upon termination.
668 ! (inout) Ocean_state - A pointer to the structure containing the internal
669 ! ocean state to be deallocated upon termination.
670 ! (in) Time - The model time, used for writing restarts.
671 
672  call ocean_model_save_restart(ocean_state, time)
673  call diag_mediator_end(time, ocean_state%MOM_CSp%diag)
674  call mom_end(ocean_state%MOM_CSp)
675  if (ocean_state%use_ice_shelf) call ice_shelf_end(ocean_state%Ice_shelf_CSp)
676 end subroutine ocean_model_end
677 ! </SUBROUTINE> NAME="ocean_model_end"
678 
679 
680 subroutine ocean_model_save_restart(OS, Time, directory, filename_suffix)
681  type(ocean_state_type), pointer :: OS
682  type(time_type), intent(in) :: Time
683  character(len=*), optional, intent(in) :: directory
684  character(len=*), optional, intent(in) :: filename_suffix
685 ! Arguments: Ocean_state - A structure containing the internal ocean state (in).
686 ! (in) Time - The model time at this call. This is needed for mpp_write calls.
687 ! (in, opt) directory - An optional directory into which to write these restart files.
688 ! (in, opt) filename_suffix - An optional suffix (e.g., a time-stamp) to append
689 ! to the restart file names.
690 
691 ! Note: This is a new routine - it will need to exist for the new incremental
692 ! checkpointing. It will also be called by ocean_model_end, giving the same
693 ! restart behavior as now in FMS.
694  character(len=200) :: restart_dir
695 
696  if (os%MOM_CSp%t_dyn_rel_adv > 0.0) call mom_error(warning, "End of MOM_main reached "//&
697  "with inconsistent dynamics and advective times. Additional restart fields "//&
698  "that have not been coded yet would be required for reproducibility.")
699  if (.not.os%fluxes%fluxes_used) call mom_error(fatal, "ocean_model_save_restart "//&
700  "was called with unused buoyancy fluxes. For conservation, the ocean "//&
701  "restart files can only be created after the buoyancy forcing is applied.")
702 
703  if (present(directory)) then ; restart_dir = directory
704  else ; restart_dir = os%dirs%restart_output_dir ; endif
705 
706  call save_restart(restart_dir, time, os%grid, os%MOM_CSp%restart_CSp, gv=os%GV)
707 
708  call forcing_save_restart(os%forcing_CSp, os%grid, time, restart_dir)
709 
710  if (os%use_ice_shelf) then
711  call ice_shelf_save_restart(os%Ice_shelf_CSp, os%Time, os%dirs%restart_output_dir)
712  endif
713 
714 end subroutine ocean_model_save_restart
715 
716 !=======================================================================
717 
718 subroutine initialize_ocean_public_type(input_domain, Ocean_sfc, diag, maskmap)
719  type(domain2d), intent(in) :: input_domain
720  type(ocean_public_type), intent(inout) :: Ocean_sfc
721  type(diag_ctrl), intent(in) :: diag
722  logical, intent(in), optional :: maskmap(:,:)
723  integer :: xsz, ysz, layout(2)
724  ! ice-ocean-boundary fields are always allocated using absolute indicies
725  ! and have no halos.
726  integer :: isc_bnd, iec_bnd, jsc_bnd, jec_bnd
727 
728  call mpp_get_layout(input_domain,layout)
729  call mpp_get_global_domain(input_domain, xsize=xsz, ysize=ysz)
730  if(PRESENT(maskmap)) then
731  call mpp_define_domains((/1,xsz,1,ysz/),layout,ocean_sfc%Domain, maskmap=maskmap)
732  else
733  call mpp_define_domains((/1,xsz,1,ysz/),layout,ocean_sfc%Domain)
734  endif
735  call mpp_get_compute_domain(ocean_sfc%Domain, isc_bnd, iec_bnd, &
736  jsc_bnd, jec_bnd)
737 
738  allocate ( ocean_sfc%t_surf (isc_bnd:iec_bnd,jsc_bnd:jec_bnd), &
739  ocean_sfc%s_surf (isc_bnd:iec_bnd,jsc_bnd:jec_bnd), &
740  ocean_sfc%u_surf (isc_bnd:iec_bnd,jsc_bnd:jec_bnd), &
741  ocean_sfc%v_surf (isc_bnd:iec_bnd,jsc_bnd:jec_bnd), &
742  ocean_sfc%sea_lev(isc_bnd:iec_bnd,jsc_bnd:jec_bnd), &
743  ocean_sfc%area (isc_bnd:iec_bnd,jsc_bnd:jec_bnd), &
744  ocean_sfc%frazil (isc_bnd:iec_bnd,jsc_bnd:jec_bnd))
745 
746  ocean_sfc%t_surf = 0.0 ! time averaged sst (Kelvin) passed to atmosphere/ice model
747  ocean_sfc%s_surf = 0.0 ! time averaged sss (psu) passed to atmosphere/ice models
748  ocean_sfc%u_surf = 0.0 ! time averaged u-current (m/sec) passed to atmosphere/ice models
749  ocean_sfc%v_surf = 0.0 ! time averaged v-current (m/sec) passed to atmosphere/ice models
750  ocean_sfc%sea_lev = 0.0 ! time averaged thickness of top model grid cell (m) plus patm/rho0/grav
751  ocean_sfc%frazil = 0.0 ! time accumulated frazil (J/m^2) passed to ice model
752  ocean_sfc%area = 0.0
753  ocean_sfc%axes = diag%axesT1%handles !diag axes to be used by coupler tracer flux diagnostics
754 
755 end subroutine initialize_ocean_public_type
756 
757 subroutine convert_state_to_ocean_type(state, Ocean_sfc, G, use_conT_absS, patm, press_to_z)
758  type(surface), intent(inout) :: state
759  type(ocean_public_type), target, intent(inout) :: Ocean_sfc
760  type(ocean_grid_type), intent(inout) :: G !< The ocean's grid structure
761  logical, intent(in) :: use_conT_absS
762  real, optional, intent(in) :: patm(:,:)
763  real, optional, intent(in) :: press_to_z
764 ! This subroutine translates the coupler's ocean_data_type into MOM's
765 ! surface state variable. This may eventually be folded into the MOM
766 ! code that calculates the surface state in the first place.
767 ! Note the offset in the arrays because the ocean_data_type has no
768 ! halo points in its arrays and always uses absolute indicies.
769  real :: IgR0
770  character(len=48) :: val_str
771  integer :: isc_bnd, iec_bnd, jsc_bnd, jec_bnd
772  integer :: i, j, i0, j0, is, ie, js, je
773 
774  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
775  call pass_vector(state%u,state%v,g%Domain)
776 
777  call mpp_get_compute_domain(ocean_sfc%Domain, isc_bnd, iec_bnd, &
778  jsc_bnd, jec_bnd)
779  if (present(patm)) then
780  ! Check that the inidicies in patm are (isc_bnd:iec_bnd,jsc_bnd:jec_bnd).
781  if (.not.present(press_to_z)) call mom_error(fatal, &
782  'convert_state_to_ocean_type: press_to_z must be present if patm is.')
783  endif
784 
785  i0 = is - isc_bnd ; j0 = js - jsc_bnd
786  !If directed convert the surface T&S
787  !from conservative T to potential T and
788  !from absolute (reference) salinity to practical salinity
789  !
790  if(use_cont_abss) then
791  do j=jsc_bnd,jec_bnd ; do i=isc_bnd,iec_bnd
792  ocean_sfc%s_surf(i,j) = gsw_sp_from_sr(state%SSS(i+i0,j+j0))
793  ocean_sfc%t_surf(i,j) = gsw_pt_from_ct(state%SSS(i+i0,j+j0),state%SST(i+i0,j+j0)) + celsius_kelvin_offset
794  enddo ; enddo
795  else
796  do j=jsc_bnd,jec_bnd ; do i=isc_bnd,iec_bnd
797  ocean_sfc%t_surf(i,j) = state%SST(i+i0,j+j0) + celsius_kelvin_offset
798  ocean_sfc%s_surf(i,j) = state%SSS(i+i0,j+j0)
799  enddo ; enddo
800  endif
801 
802  do j=jsc_bnd,jec_bnd ; do i=isc_bnd,iec_bnd
803  ocean_sfc%sea_lev(i,j) = state%sea_lev(i+i0,j+j0)
804  if (present(patm)) &
805  ocean_sfc%sea_lev(i,j) = ocean_sfc%sea_lev(i,j) + patm(i,j) * press_to_z
806  if (associated(state%frazil)) &
807  ocean_sfc%frazil(i,j) = state%frazil(i+i0,j+j0)
808  ocean_sfc%area(i,j) = g%areaT(i+i0,j+j0)
809  enddo ; enddo
810 
811  if (ocean_sfc%stagger == agrid) then
812  do j=jsc_bnd,jec_bnd ; do i=isc_bnd,iec_bnd
813  ocean_sfc%u_surf(i,j) = g%mask2dT(i+i0,j+j0)*0.5*(state%u(i+i0,j+j0)+state%u(i-1+i0,j+j0))
814  ocean_sfc%v_surf(i,j) = g%mask2dT(i+i0,j+j0)*0.5*(state%v(i+i0,j+j0)+state%v(i+i0,j-1+j0))
815  enddo ; enddo
816  elseif (ocean_sfc%stagger == bgrid_ne) then
817  do j=jsc_bnd,jec_bnd ; do i=isc_bnd,iec_bnd
818  ocean_sfc%u_surf(i,j) = g%mask2dBu(i+i0,j+j0)*0.5*(state%u(i+i0,j+j0)+state%u(i+i0,j+j0+1))
819  ocean_sfc%v_surf(i,j) = g%mask2dBu(i+i0,j+j0)*0.5*(state%v(i+i0,j+j0)+state%v(i+i0+1,j+j0))
820  enddo ; enddo
821  elseif (ocean_sfc%stagger == cgrid_ne) then
822  do j=jsc_bnd,jec_bnd ; do i=isc_bnd,iec_bnd
823  ocean_sfc%u_surf(i,j) = g%mask2dCu(i+i0,j+j0)*state%u(i+i0,j+j0)
824  ocean_sfc%v_surf(i,j) = g%mask2dCv(i+i0,j+j0)*state%v(i+i0,j+j0)
825  enddo ; enddo
826  else
827  write(val_str, '(I8)') ocean_sfc%stagger
828  call mom_error(fatal, "convert_state_to_ocean_type: "//&
829  "Ocean_sfc%stagger has the unrecognized value of "//trim(val_str))
830  endif
831 
832  if (.not.associated(state%tr_fields,ocean_sfc%fields)) &
833  call mom_error(fatal,'state%tr_fields is not pointing to Ocean_sfc%fields')
834 
835 end subroutine convert_state_to_ocean_type
836 
837 
838 !=======================================================================
839 ! <SUBROUTINE NAME="ocean_model_init_sfc">
840 !
841 ! <DESCRIPTION>
842 ! This subroutine extracts the surface properties from the ocean's internal
843 ! state and stores them in the ocean type returned to the calling ice model.
844 ! It has to be separate from the ocean_initialization call because the coupler
845 ! module allocates the space for some of these variables.
846 ! </DESCRIPTION>
847 
848 subroutine ocean_model_init_sfc(OS, Ocean_sfc)
849  type(ocean_state_type), pointer :: OS
850  type(ocean_public_type), intent(inout) :: Ocean_sfc
851 
852  call calculate_surface_state(os%state, os%MOM_CSp%u, &
853  os%MOM_CSp%v, os%MOM_CSp%h, os%MOM_CSp%ave_ssh,&
854  os%grid, os%GV, os%MOM_CSp)
855 
856  call convert_state_to_ocean_type(os%state, ocean_sfc, os%grid, os%MOM_CSp%use_conT_absS)
857 
858 end subroutine ocean_model_init_sfc
859 ! </SUBROUTINE NAME="ocean_model_init_sfc">
860 
861 ! I have no idea what the following subroutine was intended to do, but it
862 ! appears to be necessary for compiling the Memphis coupled model. In the MOM
863 ! version, it makes a call to something in the "OCEAN_TPM_MOD_FLUX_INIT". I
864 ! believe that the equivalent calls are already taken care of inside of
865 ! MOM_initialize, and given that it has no arguments, in the MOM paradigm,
866 ! it can do nothing. I think that it should be elminated. -RWH
867 
868 ! UPDATE May, 8 2007
869 ! added aof_set_couple_flux function calls to this routine. These calls
870 ! are only made by non Ocean PEs and only when CFCs are being used (though
871 ! this condition may expand. These calls are normally done during
872 ! ocean_model_init. The problem is that they are only done by Ocean PEs. All
873 ! processors need to make this call in order to get the number of ocean/atmos
874 ! fluxes correct in the coupler framework.
875 ! The trick now is to let the atmos pes know when there is no CFCs and not
876 ! to call aof_set_coupler_flux
877 !WGA
878 
879 subroutine ocean_model_flux_init(OS)
880  type(ocean_state_type), optional, pointer :: OS
881 
882  integer :: dummy
883  character(len=128) :: default_ice_restart_file, default_ocean_restart_file
884  character(len=40) :: mdl = "ocean_model_flux_init" ! This module's name.
885  type(param_file_type) :: param_file !< A structure to parse for run-time parameters
886  type(directories) :: dirs_tmp ! A structure containing several relevant directory paths.
887  logical :: use_OCMIP_CFCs, use_MOM_generic_tracer
888  logical :: OS_is_set
889 
890  os_is_set = .false. ; if (present(os)) os_is_set = associated(os)
891 
892  call get_mom_input(param_file, dirs_tmp, check_params=.false.)
893 
894  call get_param(param_file, mdl, "USE_OCMIP2_CFC", use_ocmip_cfcs, &
895  default=.false., do_not_log=.true.)
896  call get_param(param_file, mdl, "USE_generic_tracer", use_mom_generic_tracer,&
897  default=.false., do_not_log=.true.)
898 
899  call close_param_file(param_file, quiet_close=.true.)
900 
901  if(.not.os_is_set) then
902  if (use_ocmip_cfcs)then
903  default_ice_restart_file = 'ice_ocmip2_cfc.res.nc'
904  default_ocean_restart_file = 'ocmip2_cfc.res.nc'
905 
906  dummy = aof_set_coupler_flux('cfc_11_flux', &
907  flux_type = 'air_sea_gas_flux', implementation = 'ocmip2', &
908  param = (/ 9.36e-07, 9.7561e-06 /), &
909  ice_restart_file = default_ice_restart_file, &
910  ocean_restart_file = default_ocean_restart_file, &
911  caller = "register_OCMIP2_CFC")
912  dummy = aof_set_coupler_flux('cfc_12_flux', &
913  flux_type = 'air_sea_gas_flux', implementation = 'ocmip2', &
914  param = (/ 9.36e-07, 9.7561e-06 /), &
915  ice_restart_file = default_ice_restart_file, &
916  ocean_restart_file = default_ocean_restart_file, &
917  caller = "register_OCMIP2_CFC")
918  endif
919  endif
920 
921  if (use_mom_generic_tracer) then
922 #ifdef _USE_GENERIC_TRACER
923  call mom_generic_flux_init()
924 #else
925  call mom_error(fatal, &
926  "call_tracer_register: use_MOM_generic_tracer=.true. BUT not compiled with _USE_GENERIC_TRACER")
927 #endif
928  endif
929 
930 end subroutine ocean_model_flux_init
931 
932 !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!
933 ! Ocean_stock_pe - returns stocks of heat, water, etc. for conservation checks.!
934 !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!
935 subroutine ocean_stock_pe(OS, index, value, time_index)
936  use stock_constants_mod, only : istock_water, istock_heat,istock_salt
937  type(ocean_state_type), pointer :: OS
938  integer, intent(in) :: index
939  real, intent(out) :: value
940  integer, optional, intent(in) :: time_index
941 ! Arguments: OS - A structure containing the internal ocean state.
942 ! (in) index - Index of conservation quantity of interest.
943 ! (in) value - Sum returned for the conservation quantity of interest.
944 ! (in,opt) time_index - Index for time level to use if this is necessary.
945 
946  real :: to_heat, to_mass, to_salt, PSU_to_kg ! Conversion constants.
947  integer :: i, j, k, is, ie, js, je, nz, ind
948 
949  value = 0.0
950  if (.not.associated(os)) return
951  if (.not.os%is_ocean_pe) return
952 
953  is = os%grid%isc ; ie = os%grid%iec
954  js = os%grid%jsc ; je = os%grid%jec ; nz = os%grid%ke
955 
956  select case (index)
957  case (istock_water)
958  ! Return the mass of fresh water in the ocean on this PE in kg.
959  to_mass = os%GV%H_to_kg_m2
960  if (os%GV%Boussinesq) then
961  do k=1,nz ; do j=js,je ; do i=is,ie ; if (os%grid%mask2dT(i,j) > 0.5) then
962  value = value + to_mass*(os%MOM_CSp%h(i,j,k) * os%grid%areaT(i,j))
963  endif ; enddo ; enddo ; enddo
964  else
965  ! In non-Boussinesq mode, the mass of salt needs to be subtracted.
966  psu_to_kg = 1.0e-3
967  do k=1,nz ; do j=js,je ; do i=is,ie ; if (os%grid%mask2dT(i,j) > 0.5) then
968  value = value + to_mass * ((1.0 - psu_to_kg*os%MOM_CSp%tv%S(i,j,k))*&
969  (os%MOM_CSp%h(i,j,k) * os%grid%areaT(i,j)))
970  endif ; enddo ; enddo ; enddo
971  endif
972  case (istock_heat)
973  ! Return the heat content of the ocean on this PE in J.
974  to_heat = os%GV%H_to_kg_m2 * os%C_p
975  do k=1,nz ; do j=js,je ; do i=is,ie ; if (os%grid%mask2dT(i,j) > 0.5) then
976  value = value + (to_heat * os%MOM_CSp%tv%T(i,j,k)) * &
977  (os%MOM_CSp%h(i,j,k)*os%grid%areaT(i,j))
978  endif ; enddo ; enddo ; enddo
979  case (istock_salt)
980  ! Return the mass of the salt in the ocean on this PE in kg.
981  ! The 1000 converts salinity in PSU to salt in kg kg-1.
982  to_salt = os%GV%H_to_kg_m2 / 1000.0
983  do k=1,nz ; do j=js,je ; do i=is,ie ; if (os%grid%mask2dT(i,j) > 0.5) then
984  value = value + (to_salt * os%MOM_CSp%tv%S(i,j,k)) * &
985  (os%MOM_CSp%h(i,j,k)*os%grid%areaT(i,j))
986  endif ; enddo ; enddo ; enddo
987  case default ; value = 0.0
988  end select
989 
990 end subroutine ocean_stock_pe
991 
992 subroutine ocean_model_data2d_get(OS,Ocean, name, array2D,isc,jsc)
994  type(ocean_state_type), pointer :: OS
995  type(ocean_public_type), intent(in) :: Ocean
996  character(len=*) , intent(in) :: name
997  real, dimension(isc:,jsc:), intent(out):: array2D
998  integer , intent(in) :: isc,jsc
999 
1000  integer :: g_isc, g_iec, g_jsc, g_jec,g_isd, g_ied, g_jsd, g_jed, i, j
1001 
1002  if (.not.associated(os)) return
1003  if (.not.os%is_ocean_pe) return
1004 
1005 ! The problem is %areaT is on MOM domain but Ice_Ocean_Boundary%... is on mpp domain.
1006 ! We want to return the MOM data on the mpp (compute) domain
1007 ! Get MOM domain extents
1008  call mpp_get_compute_domain(os%grid%Domain%mpp_domain, g_isc, g_iec, g_jsc, g_jec)
1009  call mpp_get_data_domain (os%grid%Domain%mpp_domain, g_isd, g_ied, g_jsd, g_jed)
1010 
1011  g_isc = g_isc-g_isd+1 ; g_iec = g_iec-g_isd+1 ; g_jsc = g_jsc-g_jsd+1 ; g_jec = g_jec-g_jsd+1
1012 
1013 
1014  select case(name)
1015  case('area')
1016  array2d(isc:,jsc:) = os%grid%areaT(g_isc:g_iec,g_jsc:g_jec)
1017  case('mask')
1018  array2d(isc:,jsc:) = os%grid%mask2dT(g_isc:g_iec,g_jsc:g_jec)
1019 !OR same result
1020 ! do j=g_jsc,g_jec; do i=g_isc,g_iec
1021 ! array2D(isc+i-g_isc,jsc+j-g_jsc) = OS%grid%mask2dT(i,j)
1022 ! enddo; enddo
1023  case('t_surf')
1024  array2d(isc:,jsc:) = ocean%t_surf(isc:,jsc:)-celsius_kelvin_offset
1025  case('t_pme')
1026  array2d(isc:,jsc:) = ocean%t_surf(isc:,jsc:)-celsius_kelvin_offset
1027  case('t_runoff')
1028  array2d(isc:,jsc:) = ocean%t_surf(isc:,jsc:)-celsius_kelvin_offset
1029  case('t_calving')
1030  array2d(isc:,jsc:) = ocean%t_surf(isc:,jsc:)-celsius_kelvin_offset
1031  case('btfHeat')
1032  array2d(isc:,jsc:) = 0
1033  case default
1034  call mom_error(fatal,'get_ocean_grid_data2D: unknown argument name='//name)
1035  end select
1036 
1037 
1038 end subroutine ocean_model_data2d_get
1039 
1040 subroutine ocean_model_data1d_get(OS,Ocean, name, value)
1041  type(ocean_state_type), pointer :: OS
1042  type(ocean_public_type), intent(in) :: Ocean
1043  character(len=*) , intent(in) :: name
1044  real , intent(out):: value
1045 
1046  if (.not.associated(os)) return
1047  if (.not.os%is_ocean_pe) return
1048 
1049  select case(name)
1050  case('c_p')
1051  value = os%C_p
1052  case default
1053  call mom_error(fatal,'get_ocean_grid_data1D: unknown argument name='//name)
1054  end select
1055 
1056 
1057 end subroutine ocean_model_data1d_get
1058 
1059 subroutine ocean_public_type_chksum(id, timestep, ocn)
1061  character(len=*), intent(in) :: id
1062  integer , intent(in) :: timestep
1063  type(ocean_public_type), intent(in) :: ocn
1064  integer :: n,m, outunit
1065 
1066  outunit = stdout()
1067 
1068  write(outunit,*) "BEGIN CHECKSUM(ocean_type):: ", id, timestep
1069  write(outunit,100) 'ocean%t_surf ',mpp_chksum(ocn%t_surf )
1070  write(outunit,100) 'ocean%s_surf ',mpp_chksum(ocn%s_surf )
1071  write(outunit,100) 'ocean%u_surf ',mpp_chksum(ocn%u_surf )
1072  write(outunit,100) 'ocean%v_surf ',mpp_chksum(ocn%v_surf )
1073  write(outunit,100) 'ocean%sea_lev ',mpp_chksum(ocn%sea_lev)
1074  write(outunit,100) 'ocean%frazil ',mpp_chksum(ocn%frazil )
1075 
1076  do n = 1, ocn%fields%num_bcs !{
1077  do m = 1, ocn%fields%bc(n)%num_fields !{
1078  write(outunit,101) 'ocean%',trim(ocn%fields%bc(n)%name), &
1079  trim(ocn%fields%bc(n)%field(m)%name), &
1080  mpp_chksum(ocn%fields%bc(n)%field(m)%values)
1081  enddo !} m
1082  enddo !} n
1083 101 FORMAT(" CHECKSUM::",a6,a,'%',a," = ",z20)
1084 
1085 
1086 100 FORMAT(" CHECKSUM::",a20," = ",z20)
1087 end subroutine ocean_public_type_chksum
1088 
1089 end module ocean_model_mod
subroutine, public ocean_model_init(Ocean_sfc, OS, Time_init, Time_in)
subroutine, public diag_mediator_close_registration(diag_CS)
The following structure contains pointers to various fields which may be used describe the surface st...
subroutine, public ocean_model_restart(OS, timestamp)
subroutine, public initialize_mom(Time, param_file, dirs, CS, Time_in, offline_tracer_mode)
This subroutine initializes MOM.
Definition: MOM.F90:1480
This module implements boundary forcing for MOM6.
integer function, public aof_set_coupler_flux(name, flux_type, implementation, atm_tr_index, param, flag, ice_restart_file, ocean_restart_file, units, caller)
subroutine, public enable_averaging(time_int_in, time_end_in, diag_cs)
subroutine, public get_mom_input(param_file, dirs, check_params)
integer, parameter, public to_all
subroutine, public ocean_public_type_chksum(id, timestep, ocn)
Ocean grid type. See mom_grid for details.
Definition: MOM_grid.F90:19
This is the main routine for MOM.
Definition: MOM.F90:2
The following data type a list of diagnostic fields an their variants, as well as variables that cont...
subroutine, public ocean_stock_pe(OS, index, value, time_index)
subroutine, public tracer_flow_control_init(restart, day, G, GV, h, param_file, diag, OBC, CS, sponge_CSp, ALE_sponge_CSp, diag_to_Z_CSp, tv)
This subroutine calls all registered tracer initialization subroutines.
Provides the ocean grid type.
Definition: MOM_grid.F90:2
subroutine, public update_ocean_model(Ice_ocean_boundary, OS, Ocean_sfc, time_start_update, Ocean_coupling_time_step)
subroutine, public allocate_forcing_type(G, fluxes, stress, ustar, water, heat, shelf, press, iceberg)
Conditionally allocate fields within the forcing type.
subroutine, public call_tracer_register(HI, GV, param_file, CS, tr_Reg, restart_CS)
The following 5 subroutines and associated definitions provide the machinery to register and call the...
subroutine, public calltree_leave(mesg)
Writes a message about leaving a subroutine if call tree reporting is active.
subroutine ocean_model_data2d_get(OS, Ocean, name, array2D, isc, jsc)
This module contains I/O framework code.
Definition: MOM_io.F90:2
subroutine, public ocean_model_flux_init(OS)
subroutine, public diag_mediator_end(time, diag_CS, end_diag_manager)
subroutine, public ice_shelf_end(CS)
Deallocates all memory associated with this module.
subroutine, public forcing_accumulate(flux_tmp, fluxes, dt, G, wt2)
Accumulate the forcing over time steps.
subroutine, public accumulate_net_input(fluxes, state, dt, G, CS)
This subroutine accumates the net input of volume, and perhaps later salt and heat, through the ocean surface for use in diagnosing conservation.
Implements the thermodynamic aspects of ocean / ice-shelf interactions,.
subroutine ocean_model_data1d_get(OS, Ocean, name, value)
subroutine, public write_energy(u, v, h, tv, day, n, G, GV, CS, tracer_CSp)
This subroutine calculates and writes the total model energy, the energy and mass of each layer...
character(len=len(input_string)) function, public uppercase(input_string)
subroutine, public close_param_file(CS, quiet_close, component)
subroutine, public ice_shelf_save_restart(CS, Time, directory, time_stamped, filename_suffix)
Save the ice shelf restart file.
subroutine, public ocean_model_init_sfc(OS, Ocean_sfc)
logical function, public is_root_pe()
subroutine, public forcing_diagnostics(fluxes, state, dt, G, diag, handles)
Offer buoyancy forcing fields for diagnostics for those fields registered as part of register_forcing...
subroutine, public forcing_save_restart(CS, G, Time, directory, time_stamped, filename_suffix)
Control structure for this module.
Definition: MOM.F90:148
real, parameter, public celsius_kelvin_offset
subroutine, public ocean_model_end(Ocean_sfc, Ocean_state, Time)
subroutine, public initialize_ice_shelf(param_file, ocn_grid, Time, CS, diag, fluxes, Time_in, solo_ice_sheet_in)
Initializes shelf model data, parameters and diagnostics.
Structure that contains pointers to the boundary forcing used to drive the liquid ocean simulated by ...
Provides subroutines for quantities specific to the equation of state.
Definition: MOM_EOS.F90:2
Control structure that contains ice shelf parameters and diagnostics handles.
subroutine, public calculate_surface_state(state, u, v, h, ssh, G, GV, CS)
This subroutine sets the surface (return) properties of the ocean model by setting the appropriate fi...
Definition: MOM.F90:3441
subroutine add_berg_flux_to_shelf(G, fluxes, use_ice_shelf, density_ice, kv_ice, latent_heat_fusion, state, time_step, berg_area_threshold)
subroutine, public step_offline(fluxes, state, Time_start, time_interval, CS)
step_offline is the main driver for running tracers offline in MOM6. This has been primarily develope...
Definition: MOM.F90:1294
subroutine, public save_restart(directory, time, G, CS, time_stamped, filename, GV)
subroutine, public step_mom(fluxes, state, Time_start, time_interval, CS)
This subroutine orchestrates the time stepping of MOM. The adiabatic dynamics are stepped by calls to...
Definition: MOM.F90:466
subroutine, public ocean_model_save_restart(OS, Time, directory, filename_suffix)
subroutine, public disable_averaging(diag_cs)
subroutine convert_state_to_ocean_type(state, Ocean_sfc, G, use_conT_absS, patm, press_to_z)
subroutine initialize_ocean_public_type(input_domain, Ocean_sfc, diag, maskmap)
subroutine, public mom_end(CS)
End of model.
Definition: MOM.F90:3746
subroutine, public surface_forcing_init(Time, G, param_file, diag, CS, tracer_flow_CSp)
subroutine, public mom_error(level, message, all_print)
subroutine, public mech_forcing_diags(fluxes, dt, G, diag, handles)
Offer mechanical forcing fields for diagnostics for those fields registered as part of register_forci...
subroutine, public finish_mom_initialization(Time, dirs, CS, fluxes)
This subroutine finishes initializing MOM and writes out the initial conditions.
Definition: MOM.F90:2345
subroutine, public shelf_calc_flux(state, fluxes, Time, time_step, CS)
Calculates fluxes between the ocean and ice-shelf using the three-equations formulation (optional to ...
subroutine, public mom_sum_output_init(G, param_file, directory, ntrnc, Input_start_time, CS)
subroutine, public calltree_enter(mesg, n)
Writes a message about entering a subroutine if call tree reporting is active.