80 implicit none ;
private 82 #include <MOM_memory.h> 90 real,
dimension(:,:,:),
pointer :: p => null()
95 logical :: coupled_tracers = .false.
97 real,
allocatable,
dimension(:) :: dye_source_minlon, &
101 dye_source_mindepth, &
104 real,
pointer :: tr(:,:,:,:) => null()
106 type(
p3d),
allocatable,
dimension(:) :: &
112 integer,
allocatable,
dimension(:) :: &
115 id_tracer, id_tr_adx, id_tr_ady, &
123 logical :: tracers_may_reinit = .false.
148 #include "version_variable.h" 149 character(len=40) :: mdl =
"regional_dyes" 150 character(len=200) :: inputdir
151 character(len=48) :: var_name
152 character(len=48) :: desc_name
153 real,
pointer :: tr_ptr(:,:,:) => null()
154 logical :: register_dye_tracer
155 integer :: isd, ied, jsd, jed, nz, m
156 isd = hi%isd ; ied = hi%ied ; jsd = hi%jsd ; jed = hi%jed ; nz = gv%ke
158 if (
associated(cs))
then 159 call mom_error(warning,
"register_dye_tracer called with an "// &
160 "associated control structure.")
167 call get_param(param_file, mdl,
"NUM_DYE_TRACERS", cs%ntr, &
168 "The number of dye tracers in this run. Each tracer \n"//&
169 "should have a separate region.", default=0)
170 allocate(cs%dye_source_minlon(cs%ntr), &
171 cs%dye_source_maxlon(cs%ntr), &
172 cs%dye_source_minlat(cs%ntr), &
173 cs%dye_source_maxlat(cs%ntr), &
174 cs%dye_source_mindepth(cs%ntr), &
175 cs%dye_source_maxdepth(cs%ntr))
176 allocate(cs%tr_adx(cs%ntr), &
180 allocate(cs%ind_tr(cs%ntr), &
181 cs%id_tracer(cs%ntr), &
182 cs%id_tr_adx(cs%ntr), &
183 cs%id_tr_ady(cs%ntr), &
184 cs%id_tr_dfx(cs%ntr), &
185 cs%id_tr_dfy(cs%ntr))
186 allocate(cs%tr_desc(cs%ntr))
194 cs%dye_source_minlon(:) = -1.e30
195 call get_param(param_file, mdl,
"DYE_SOURCE_MINLON", cs%dye_source_minlon, &
196 "This is the starting longitude at which we start injecting dyes.", &
197 fail_if_missing=.true.)
198 if (minval(cs%dye_source_minlon(:)) < -1.e29) &
199 call mom_error(fatal,
"register_dye_tracer: Not enough values provided for DYE_SOURCE_MINLON ")
201 cs%dye_source_maxlon(:) = -1.e30
202 call get_param(param_file, mdl,
"DYE_SOURCE_MAXLON", cs%dye_source_maxlon, &
203 "This is the ending longitude at which we finish injecting dyes.", &
204 fail_if_missing=.true.)
205 if (minval(cs%dye_source_maxlon(:)) < -1.e29) &
206 call mom_error(fatal,
"register_dye_tracer: Not enough values provided for DYE_SOURCE_MAXLON ")
208 cs%dye_source_minlat(:) = -1.e30
209 call get_param(param_file, mdl,
"DYE_SOURCE_MINLAT", cs%dye_source_minlat, &
210 "This is the starting latitude at which we start injecting dyes.", &
211 fail_if_missing=.true.)
212 if (minval(cs%dye_source_minlat(:)) < -1.e29) &
213 call mom_error(fatal,
"register_dye_tracer: Not enough values provided for DYE_SOURCE_MINLAT ")
215 cs%dye_source_maxlat(:) = -1.e30
216 call get_param(param_file, mdl,
"DYE_SOURCE_MAXLAT", cs%dye_source_maxlat, &
217 "This is the ending latitude at which we finish injecting dyes.", &
218 fail_if_missing=.true.)
219 if (minval(cs%dye_source_maxlat(:)) < -1.e29) &
220 call mom_error(fatal,
"register_dye_tracer: Not enough values provided for DYE_SOURCE_MAXLAT ")
222 cs%dye_source_mindepth(:) = -1.e30
223 call get_param(param_file, mdl,
"DYE_SOURCE_MINDEPTH", cs%dye_source_mindepth, &
224 "This is the minumum depth at which we inject dyes.", &
225 fail_if_missing=.true.)
226 if (minval(cs%dye_source_mindepth(:)) < -1.e29) &
227 call mom_error(fatal,
"register_dye_tracer: Not enough values provided for DYE_SOURCE_MINDEPTH")
229 cs%dye_source_maxdepth(:) = -1.e30
230 call get_param(param_file, mdl,
"DYE_SOURCE_MAXDEPTH", cs%dye_source_maxdepth, &
231 "This is the maximum depth at which we inject dyes.", &
232 fail_if_missing=.true.)
233 if (minval(cs%dye_source_maxdepth(:)) < -1.e29) &
234 call mom_error(fatal,
"register_dye_tracer: Not enough values provided for DYE_SOURCE_MAXDEPTH ")
237 write(var_name(:),
'(A,I3.3)')
"dye",m
238 write(desc_name(:),
'(A,I3.3)')
"Dye Tracer ",m
239 cs%tr_desc(m) =
var_desc(trim(var_name),
"conc", trim(desc_name), caller=mdl)
244 allocate(cs%tr(isd:ied,jsd:jed,nz,cs%ntr)) ; cs%tr(:,:,:,:) = 0.0
249 tr_ptr => cs%tr(:,:,:,m)
251 caller=
"register_dye_tracer")
254 .not.cs%tracers_may_reinit, restart_cs)
256 call register_tracer(tr_ptr, cs%tr_desc(m), param_file, hi, gv, tr_reg, &
257 tr_desc_ptr=cs%tr_desc(m))
262 if (cs%coupled_tracers) &
264 flux_type=
' ', implementation=
' ', caller=
"register_dye_tracer")
268 cs%restart_CSp => restart_cs
269 register_dye_tracer = .true.
274 logical,
intent(in) :: restart
275 type(time_type),
target,
intent(in) :: day
278 real,
dimension(NIMEM_,NJMEM_,NKMEM_),
intent(in) :: h
279 type(
diag_ctrl),
target,
intent(in) :: diag
301 character(len=24) :: name
302 character(len=72) :: longname
303 character(len=48) :: units
304 character(len=48) :: flux_units
307 integer :: i, j, k, m
308 real :: z_bot, z_center
310 if (.not.
associated(cs))
return 311 if (cs%ntr < 1)
return 317 do j=g%jsd,g%jed ;
do i=g%isd,g%ied
319 if (cs%dye_source_minlon(m)<g%geoLonT(i,j) .and. &
320 cs%dye_source_maxlon(m)>=g%geoLonT(i,j) .and. &
321 cs%dye_source_minlat(m)<g%geoLatT(i,j) .and. &
322 cs%dye_source_maxlat(m)>=g%geoLatT(i,j) .and. &
323 g%mask2dT(i,j) > 0.0 )
then 324 z_bot = -g%bathyT(i,j)
326 z_center = z_bot + 0.5*h(i,j,k)*gv%H_to_m
327 if ( z_center > -cs%dye_source_maxdepth(m) .and. &
328 z_center < -cs%dye_source_mindepth(m) )
then 331 z_bot = z_bot + h(i,j,k)*gv%H_to_m
339 call query_vardesc(cs%tr_desc(m), name, units=units, longname=longname, &
340 caller=
"initialize_dye_tracer")
341 cs%id_tracer(m) = register_diag_field(
"ocean_model", trim(name), cs%diag%axesTL, &
342 day, trim(longname) , trim(units))
343 cs%id_tr_adx(m) = register_diag_field(
"ocean_model", trim(name)//
"_adx", &
344 cs%diag%axesCuL, day, trim(longname)//
" advective zonal flux" , &
346 cs%id_tr_ady(m) = register_diag_field(
"ocean_model", trim(name)//
"_ady", &
347 cs%diag%axesCvL, day, trim(longname)//
" advective meridional flux" , &
349 cs%id_tr_dfx(m) = register_diag_field(
"ocean_model", trim(name)//
"_dfx", &
350 cs%diag%axesCuL, day, trim(longname)//
" diffusive zonal flux" , &
352 cs%id_tr_dfy(m) = register_diag_field(
"ocean_model", trim(name)//
"_dfy", &
353 cs%diag%axesCvL, day, trim(longname)//
" diffusive zonal flux" , &
355 if (cs%id_tr_adx(m) > 0)
call safe_alloc_ptr(cs%tr_adx(m)%p,g%IsdB,g%IedB,g%jsd,g%jed,gv%ke)
356 if (cs%id_tr_ady(m) > 0)
call safe_alloc_ptr(cs%tr_ady(m)%p,g%isd,g%ied,g%JsdB,g%JedB,gv%ke)
357 if (cs%id_tr_dfx(m) > 0)
call safe_alloc_ptr(cs%tr_dfx(m)%p,g%IsdB,g%IedB,g%jsd,g%jed,gv%ke)
358 if (cs%id_tr_dfy(m) > 0)
call safe_alloc_ptr(cs%tr_dfy(m)%p,g%isd,g%ied,g%JsdB,g%JedB,gv%ke)
361 if ((cs%id_tr_adx(m) > 0) .or. (cs%id_tr_ady(m) > 0) .or. &
362 (cs%id_tr_dfx(m) > 0) .or. (cs%id_tr_dfy(m) > 0)) &
364 cs%tr_ady(m)%p,cs%tr_dfx(m)%p,cs%tr_dfy(m)%p)
367 day, g, diag_to_z_csp)
373 evap_CFL_limit, minimum_forcing_depth)
374 real,
dimension(NIMEM_,NJMEM_,NKMEM_),
intent(in) :: h_old, h_new, ea, eb
375 type(forcing),
intent(in) :: fluxes
376 real,
intent(in) :: dt
377 type(ocean_grid_type),
intent(in) :: G
378 type(verticalgrid_type),
intent(in) :: GV
380 real,
optional,
intent(in) :: evap_CFL_limit
381 real,
optional,
intent(in) :: minimum_forcing_depth
404 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)) :: h_work
406 real :: Isecs_per_year
408 integer :: secs, days
409 integer :: i, j, k, is, ie, js, je, nz, m
410 real :: z_bot, z_center
412 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = gv%ke
414 if (.not.
associated(cs))
return 415 if (cs%ntr < 1)
return 417 if (
present(evap_cfl_limit) .and.
present(minimum_forcing_depth))
then 419 do k=1,nz ;
do j=js,je ;
do i=is,ie
420 h_work(i,j,k) = h_old(i,j,k)
421 enddo ;
enddo ; enddo;
422 call applytracerboundaryfluxesinout(g, gv, cs%tr(:,:,:,m) , dt, fluxes, h_work, &
423 evap_cfl_limit, minimum_forcing_depth)
424 call tracer_vertdiff(h_work, ea, eb, dt, cs%tr(:,:,:,m), g, gv)
428 call tracer_vertdiff(h_old, ea, eb, dt, cs%tr(:,:,:,m), g, gv)
433 do j=g%jsd,g%jed ;
do i=g%isd,g%ied
435 if (cs%dye_source_minlon(m)<g%geoLonT(i,j) .and. &
436 cs%dye_source_maxlon(m)>=g%geoLonT(i,j) .and. &
437 cs%dye_source_minlat(m)<g%geoLatT(i,j) .and. &
438 cs%dye_source_maxlat(m)>=g%geoLatT(i,j) .and. &
439 g%mask2dT(i,j) > 0.0 )
then 440 z_bot = -g%bathyT(i,j)
442 z_center = z_bot + 0.5*h_new(i,j,k)*gv%H_to_m
443 if ( z_center > -cs%dye_source_maxdepth(m) .and. &
444 z_center < -cs%dye_source_mindepth(m) )
then 447 z_bot = z_bot + h_new(i,j,k)*gv%H_to_m
455 if (cs%id_tracer(m)>0) &
456 call post_data(cs%id_tracer(m),cs%tr(:,:,:,m),cs%diag)
457 if (cs%id_tr_adx(m)>0) &
458 call post_data(cs%id_tr_adx(m),cs%tr_adx(m)%p(:,:,:),cs%diag)
459 if (cs%id_tr_ady(m)>0) &
460 call post_data(cs%id_tr_ady(m),cs%tr_ady(m)%p(:,:,:),cs%diag)
461 if (cs%id_tr_dfx(m)>0) &
462 call post_data(cs%id_tr_dfx(m),cs%tr_dfx(m)%p(:,:,:),cs%diag)
463 if (cs%id_tr_dfy(m)>0) &
464 call post_data(cs%id_tr_dfy(m),cs%tr_dfy(m)%p(:,:,:),cs%diag)
469 function dye_stock(h, stocks, G, GV, CS, names, units, stock_index)
470 real,
dimension(NIMEM_,NJMEM_,NKMEM_),
intent(in) :: h
471 real,
dimension(:),
intent(out) :: stocks
472 type(ocean_grid_type),
intent(in) :: G
473 type(verticalgrid_type),
intent(in) :: GV
475 character(len=*),
dimension(:),
intent(out) :: names
476 character(len=*),
dimension(:),
intent(out) :: units
477 integer,
optional,
intent(in) :: stock_index
495 integer :: i, j, k, is, ie, js, je, nz, m
496 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = gv%ke
499 if (.not.
associated(cs))
return 500 if (cs%ntr < 1)
return 502 if (
present(stock_index))
then ;
if (stock_index > 0)
then 510 call query_vardesc(cs%tr_desc(m), name=names(m), units=units(m), caller=
"dye_stock")
511 units(m) = trim(units(m))//
" kg" 513 do k=1,nz ;
do j=js,je ;
do i=is,ie
514 stocks(m) = stocks(m) + cs%tr(i,j,k,m) * &
515 (g%mask2dT(i,j) * g%areaT(i,j) * h(i,j,k))
516 enddo ;
enddo ;
enddo 517 stocks(m) = gv%H_to_kg_m2 * stocks(m)
524 type(surface),
intent(inout) :: state
525 real,
dimension(NIMEM_,NJMEM_,NKMEM_),
intent(in) :: h
526 type(ocean_grid_type),
intent(in) :: G
536 integer :: i, j, m, is, ie, js, je
537 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
539 if (.not.
associated(cs))
return 541 if (cs%coupled_tracers)
then 545 call set_coupler_values(cs%tr(:,:,1,m), state%tr_fields, cs%ind_tr(m), &
546 ind_csurf, is, ie, js, je)
556 if (
associated(cs))
then 557 if (
associated(cs%tr))
deallocate(cs%tr)
559 if (
associated(cs%tr_adx(m)%p))
deallocate(cs%tr_adx(m)%p)
560 if (
associated(cs%tr_ady(m)%p))
deallocate(cs%tr_ady(m)%p)
561 if (
associated(cs%tr_dfx(m)%p))
deallocate(cs%tr_dfx(m)%p)
562 if (
associated(cs%tr_dfy(m)%p))
deallocate(cs%tr_dfy(m)%p)
The following structure contains pointers to various fields which may be used describe the surface st...
logical function, public register_dye_tracer(HI, GV, param_file, CS, tr_Reg, restart_CS)
subroutine, public regional_dyes_end(CS)
type(vardesc) function, public var_desc(name, units, longname, hor_grid, z_grid, t_grid, cmor_field_name, cmor_units, conversion, caller)
Returns a vardesc type whose elements have been filled with the provided fields. The argument name is...
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)
logical function, public tracer_z_init(tr, h, filename, tr_name, G, missing_val, land_val)
Ocean grid type. See mom_grid for details.
Provides the ocean grid type.
integer function, public dye_stock(h, stocks, G, GV, CS, names, units, stock_index)
This module contains I/O framework code.
Defines the horizontal index type (hor_index_type) used for providing index ranges.
Container for horizontal index ranges for data, computational and global domains. ...
subroutine, public register_tracer(tr1, tr_desc, param_file, HI, GV, Reg, tr_desc_ptr, ad_x, ad_y, df_x, df_y, OBC_inflow, OBC_in_u, OBC_in_v, ad_2d_x, ad_2d_y, df_2d_x, df_2d_y, advection_xy)
This subroutine registers a tracer to be advected and laterally diffused.
This module contains the tracer_registry_type and the subroutines that handle registration of tracers...
subroutine, public applytracerboundaryfluxesinout(G, GV, Tr, dt, fluxes, h, evap_CFL_limit, minimum_forcing_depth, in_flux_optional, out_flux_optional, update_h_opt)
This routine is modeled after applyBoundaryFluxesInOut in MOM_diabatic_aux.F90 NOTE: Please note that...
subroutine, public set_up_sponge_field(sp_val, f_ptr, G, nlay, CS, sp_val_i_mean)
Type to carry basic tracer information.
This module contains routines that implement physical fluxes of tracers (e.g. due to surface fluxes o...
subroutine, public register_z_tracer(tr_ptr, name, long_name, units, Time, G, CS, standard_name, cmor_field_name, cmor_long_name, cmor_units, cmor_standard_name)
This subroutine registers a tracer to be output in depth space.
subroutine, public add_tracer_obc_values(name, Reg, OBC_inflow, OBC_in_u, OBC_in_v)
This subroutine adds open boundary condition concentrations for a tracer that has previously been reg...
subroutine, public add_tracer_diagnostics(name, Reg, ad_x, ad_y, df_x, df_y, ad_2d_x, ad_2d_y, df_2d_x, df_2d_y, advection_xy)
This subroutine adds diagnostic arrays for a tracer that has previously been registered by a call to ...
Structure that contains pointers to the boundary forcing used to drive the liquid ocean simulated by ...
subroutine, public set_coupler_values(array_in, BC_struc, BC_index, BC_element, is, ie, js, je, conversion)
Type for describing a variable, typically a tracer.
subroutine, public tracer_vertdiff(h_old, ea, eb, dt, tr, G, GV, sfc_flux, btm_flux, btm_reservoir, sink_rate, convert_flux_in)
This subroutine solves a tridiagonal equation for the final tracer concentrations after the dual-entr...
subroutine, public initialize_dye_tracer(restart, day, G, GV, h, diag, OBC, CS, sponge_CSp, diag_to_Z_CSp)
subroutine, public query_vardesc(vd, name, units, longname, hor_grid, z_grid, t_grid, cmor_field_name, cmor_units, conversion, caller)
This routine queries vardesc.
Controls where open boundary conditions are applied.
subroutine, public dye_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, G, GV, CS, evap_CFL_limit, minimum_forcing_depth)
subroutine, public mom_error(level, message, all_print)
subroutine, public dye_tracer_surface_state(state, h, G, CS)