78 implicit none ;
private 80 #include <MOM_memory.h> 87 integer,
parameter ::
ntr = 11
90 real,
dimension(:,:,:),
pointer :: p => null()
95 logical :: coupled_tracers = .false.
97 character(len=200) :: tracer_ic_file
99 type(time_type),
pointer :: time
101 real,
pointer :: tr(:,:,:,:) => null()
103 real,
pointer :: tr_aux(:,:,:,:) => null()
105 type(
p3d),
dimension(NTR) :: &
110 real :: land_val(
ntr) = -1.0
111 logical :: mask_tracers
112 logical :: use_sponge
113 logical :: tracers_may_reinit
115 real :: x_origin, x_width
116 real :: y_origin, y_width
118 integer,
dimension(NTR) :: ind_tr
126 integer,
dimension(NTR) :: id_tracer = -1, id_tr_adx = -1, id_tr_ady = -1
127 integer,
dimension(NTR) :: id_tr_dfx = -1, id_tr_dfy = -1
152 character(len=80) :: name, longname
154 #include "version_variable.h" 155 character(len=40) :: mdl =
"advection_test_tracer" 156 character(len=200) :: inputdir
157 real,
pointer :: tr_ptr(:,:,:) => null()
158 logical :: register_advection_test_tracer
159 integer :: isd, ied, jsd, jed, nz, m
160 isd = hi%isd ; ied = hi%ied ; jsd = hi%jsd ; jed = hi%jed ; nz = gv%ke
162 if (
associated(cs))
then 163 call mom_error(warning,
"register_advection_test_tracer called with an "// &
164 "associated control structure.")
172 call get_param(param_file, mdl,
"ADVECTION_TEST_X_ORIGIN", cs%x_origin, &
173 "The x-coorindate of the center of the test-functions.\n", default=0.)
174 call get_param(param_file, mdl,
"ADVECTION_TEST_Y_ORIGIN", cs%y_origin, &
175 "The y-coorindate of the center of the test-functions.\n", default=0.)
176 call get_param(param_file, mdl,
"ADVECTION_TEST_X_WIDTH", cs%x_width, &
177 "The x-width of the test-functions.\n", default=0.)
178 call get_param(param_file, mdl,
"ADVECTION_TEST_Y_WIDTH", cs%y_width, &
179 "The y-width of the test-functions.\n", default=0.)
180 call get_param(param_file, mdl,
"ADVECTION_TEST_TRACER_IC_FILE", cs%tracer_IC_file, &
181 "The name of a file from which to read the initial \n"//&
182 "conditions for the tracers, or blank to initialize \n"//&
183 "them internally.", default=
" ")
185 if (len_trim(cs%tracer_IC_file) >= 1)
then 186 call get_param(param_file, mdl,
"INPUTDIR", inputdir, default=
".")
187 cs%tracer_IC_file = trim(slasher(inputdir))//trim(cs%tracer_IC_file)
188 call log_param(param_file, mdl,
"INPUTDIR/ADVECTION_TEST_TRACER_IC_FILE", &
191 call get_param(param_file, mdl,
"SPONGE", cs%use_sponge, &
192 "If true, sponges may be applied anywhere in the domain. \n"//&
193 "The exact location and properties of those sponges are \n"//&
194 "specified from MOM_initialization.F90.", default=.false.)
196 call get_param(param_file, mdl,
"MASK_TRACERS_IN_MASSLESS_LAYERS", cs%mask_tracers, &
197 "If true, tracers will be masked out in massless layers. \n", &
199 call get_param(param_file, mdl,
"TRACERS_MAY_REINIT", cs%tracers_may_reinit, &
200 "If true, tracers may go through the initialization code \n"//&
201 "if they are not found in the restart files. Otherwise \n"//&
202 "it is a fatal error if the tracers are not found in the \n"//&
203 "restart files of a restarted run.", default=.false.)
206 allocate(cs%tr(isd:ied,jsd:jed,nz,
ntr)) ; cs%tr(:,:,:,:) = 0.0
207 if (cs%mask_tracers)
then 208 allocate(cs%tr_aux(isd:ied,jsd:jed,nz,
ntr)) ; cs%tr_aux(:,:,:,:) = 0.0
212 if (m < 10)
then ;
write(name,
'("tr",I1.1)') m
213 else ;
write(name,
'("tr",I2.2)') m ;
endif 214 write(longname,
'("Concentration of Tracer ",I2.2)') m
215 cs%tr_desc(m) =
var_desc(name, units=
"kg kg-1", longname=longname, caller=mdl)
219 tr_ptr => cs%tr(:,:,:,m)
222 .not. cs%tracers_may_reinit, restart_cs)
224 call register_tracer(tr_ptr, cs%tr_desc(m), param_file, hi, gv, tr_reg, &
225 tr_desc_ptr=cs%tr_desc(m))
230 if (cs%coupled_tracers) &
232 flux_type=
' ', implementation=
' ', caller=
"register_advection_test_tracer")
236 cs%restart_CSp => restart_cs
237 register_advection_test_tracer = .true.
241 sponge_CSp, diag_to_Z_CSp)
242 logical,
intent(in) :: restart
243 type(time_type),
target,
intent(in) :: day
246 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h
247 type(
diag_ctrl),
target,
intent(in) :: diag
270 real,
allocatable :: temp(:,:,:)
271 real,
pointer,
dimension(:,:,:) :: &
272 OBC_tr1_u => null(), &
276 character(len=16) :: name
277 character(len=72) :: longname
278 character(len=48) :: units
279 character(len=48) :: flux_units
281 real,
pointer :: tr_ptr(:,:,:) => null()
287 integer :: i, j, k, is, ie, js, je, isd, ied, jsd, jed, nz, m
288 integer :: IsdB, IedB, JsdB, JedB
289 real :: tmpx, tmpy, locx, locy
291 if (.not.
associated(cs))
return 292 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = gv%ke
293 isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
294 isdb = g%IsdB ; iedb = g%IedB ; jsdb = g%JsdB ; jedb = g%JedB
295 h_neglect = gv%H_subroundoff
301 caller=
"initialize_advection_test_tracer")
302 if ((.not.restart) .or. (cs%tracers_may_reinit .and. .not. &
304 do k=1,nz ;
do j=js,je ;
do i=is,ie
306 enddo ;
enddo ;
enddo 308 do j=js,je ;
do i=is,ie
309 if (abs(g%geoLonT(i,j)-cs%x_origin)<0.5*cs%x_width .and. &
310 abs(g%geoLatT(i,j)-cs%y_origin)<0.5*cs%y_width) cs%tr(i,j,k,m) = 1.0
313 do j=js,je ;
do i=is,ie
314 locx=abs(g%geoLonT(i,j)-cs%x_origin)/cs%x_width
315 locy=abs(g%geoLatT(i,j)-cs%y_origin)/cs%y_width
316 cs%tr(i,j,k,m) = max(0.0, 1.0-locx)*max(0.0, 1.0-locy)
319 do j=js,je ;
do i=is,ie
320 locx=min(1.0, abs(g%geoLonT(i,j)-cs%x_origin)/cs%x_width)*(acos(0.0)*2.)
321 locy=min(1.0, abs(g%geoLatT(i,j)-cs%y_origin)/cs%y_width)*(acos(0.0)*2.)
322 cs%tr(i,j,k,m) = (1.0+cos(locx))*(1.0+cos(locy))*0.25
325 do j=js,je ;
do i=is,ie
326 locx=abs(g%geoLonT(i,j)-cs%x_origin)/cs%x_width
327 locy=abs(g%geoLatT(i,j)-cs%y_origin)/cs%y_width
328 if (locx**2+locy**2<=1.0) cs%tr(i,j,k,m) = 1.0
331 do j=js,je ;
do i=is,ie
332 locx=(g%geoLonT(i,j)-cs%x_origin)/cs%x_width
333 locy=(g%geoLatT(i,j)-cs%y_origin)/cs%y_width
334 if (locx**2+locy**2<=1.0) cs%tr(i,j,k,m) = 1.0
335 if (locx>0.0.and.abs(locy)<0.2) cs%tr(i,j,k,m) = 0.0
342 if (gv%Boussinesq)
then ; flux_units =
"kg kg-1 m3 s-1" 343 else ; flux_units =
"kg s-1" ;
endif 347 call query_vardesc(cs%tr_desc(m), name, units=units, longname=longname, &
348 caller=
"initialize_advection_test_tracer")
349 cs%id_tracer(m) = register_diag_field(
"ocean_model", trim(name), cs%diag%axesTL, &
350 day, trim(longname) , trim(units))
351 cs%id_tr_adx(m) = register_diag_field(
"ocean_model", trim(name)//
"_adx", &
352 cs%diag%axesCuL, day, trim(longname)//
" advective zonal flux" , &
354 cs%id_tr_ady(m) = register_diag_field(
"ocean_model", trim(name)//
"_ady", &
355 cs%diag%axesCvL, day, trim(longname)//
" advective meridional flux" , &
357 cs%id_tr_dfx(m) = register_diag_field(
"ocean_model", trim(name)//
"_dfx", &
358 cs%diag%axesCuL, day, trim(longname)//
" diffusive zonal flux" , &
360 cs%id_tr_dfy(m) = register_diag_field(
"ocean_model", trim(name)//
"_dfy", &
361 cs%diag%axesCvL, day, trim(longname)//
" diffusive zonal flux" , &
363 if (cs%id_tr_adx(m) > 0)
call safe_alloc_ptr(cs%tr_adx(m)%p,isdb,iedb,jsd,jed,nz)
364 if (cs%id_tr_ady(m) > 0)
call safe_alloc_ptr(cs%tr_ady(m)%p,isd,ied,jsdb,jedb,nz)
365 if (cs%id_tr_dfx(m) > 0)
call safe_alloc_ptr(cs%tr_dfx(m)%p,isdb,iedb,jsd,jed,nz)
366 if (cs%id_tr_dfy(m) > 0)
call safe_alloc_ptr(cs%tr_dfy(m)%p,isd,ied,jsdb,jedb,nz)
369 if ((cs%id_tr_adx(m) > 0) .or. (cs%id_tr_ady(m) > 0) .or. &
370 (cs%id_tr_dfx(m) > 0) .or. (cs%id_tr_dfy(m) > 0)) &
372 cs%tr_ady(m)%p,cs%tr_dfx(m)%p,cs%tr_dfy(m)%p)
375 day, g, diag_to_z_csp)
382 evap_CFL_limit, minimum_forcing_depth)
385 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h_old, h_new, ea, eb
386 type(
forcing),
intent(in) :: fluxes
387 real,
intent(in) :: dt
389 real,
optional,
intent(in) :: evap_CFL_limit
390 real,
optional,
intent(in) :: minimum_forcing_depth
413 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)) :: h_work
415 real :: c1(szi_(g),szk_(g))
416 integer :: i, j, k, is, ie, js, je, nz, m
417 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = gv%ke
419 if (.not.
associated(cs))
return 421 if (
present(evap_cfl_limit) .and.
present(minimum_forcing_depth))
then 423 do k=1,nz ;
do j=js,je ;
do i=is,ie
424 h_work(i,j,k) = h_old(i,j,k)
425 enddo ;
enddo ; enddo;
427 evap_cfl_limit, minimum_forcing_depth)
436 if (cs%mask_tracers)
then 437 do m = 1,
ntr ;
if (cs%id_tracer(m) > 0)
then 438 do k=1,nz ;
do j=js,je ;
do i=is,ie
439 if (h_new(i,j,k) < 1.1*gv%Angstrom)
then 440 cs%tr_aux(i,j,k,m) = cs%land_val(m)
442 cs%tr_aux(i,j,k,m) = cs%tr(i,j,k,m)
444 enddo ;
enddo ;
enddo 449 if (cs%mask_tracers)
then 450 if (cs%id_tracer(m)>0) &
451 call post_data(cs%id_tracer(m),cs%tr_aux(:,:,:,m),cs%diag)
453 if (cs%id_tracer(m)>0) &
454 call post_data(cs%id_tracer(m),cs%tr(:,:,:,m),cs%diag)
456 if (cs%id_tr_adx(m)>0) &
457 call post_data(cs%id_tr_adx(m),cs%tr_adx(m)%p(:,:,:),cs%diag)
458 if (cs%id_tr_ady(m)>0) &
459 call post_data(cs%id_tr_ady(m),cs%tr_ady(m)%p(:,:,:),cs%diag)
460 if (cs%id_tr_dfx(m)>0) &
461 call post_data(cs%id_tr_dfx(m),cs%tr_dfx(m)%p(:,:,:),cs%diag)
462 if (cs%id_tr_dfy(m)>0) &
463 call post_data(cs%id_tr_dfy(m),cs%tr_dfy(m)%p(:,:,:),cs%diag)
469 type(
surface),
intent(inout) :: state
470 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h
480 integer :: i, j, m, is, ie, js, je
481 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
483 if (.not.
associated(cs))
return 485 if (cs%coupled_tracers)
then 490 ind_csurf, is, ie, js, je)
497 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h
498 real,
dimension(:),
intent(out) :: stocks
501 character(len=*),
dimension(:),
intent(out) :: names
502 character(len=*),
dimension(:),
intent(out) :: units
503 integer,
optional,
intent(in) :: stock_index
504 integer :: advection_test_stock
521 integer :: i, j, k, is, ie, js, je, nz, m
522 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = gv%ke
524 advection_test_stock = 0
525 if (.not.
associated(cs))
return 526 if (cs%ntr < 1)
return 528 if (
present(stock_index))
then ;
if (stock_index > 0)
then 536 call query_vardesc(cs%tr_desc(m), name=names(m), units=units(m), caller=
"advection_test_stock")
538 do k=1,nz ;
do j=js,je ;
do i=is,ie
539 stocks(m) = stocks(m) + cs%tr(i,j,k,m) * &
540 (g%mask2dT(i,j) * g%areaT(i,j) * h(i,j,k))
541 enddo ;
enddo ;
enddo 542 stocks(m) = gv%H_to_kg_m2 * stocks(m)
544 advection_test_stock = cs%ntr
552 if (
associated(cs))
then 553 if (
associated(cs%tr))
deallocate(cs%tr)
554 if (
associated(cs%tr_aux))
deallocate(cs%tr_aux)
556 if (
associated(cs%tr_adx(m)%p))
deallocate(cs%tr_adx(m)%p)
557 if (
associated(cs%tr_ady(m)%p))
deallocate(cs%tr_ady(m)%p)
558 if (
associated(cs%tr_dfx(m)%p))
deallocate(cs%tr_dfx(m)%p)
559 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...
subroutine, public advection_test_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, G, GV, CS, evap_CFL_limit, minimum_forcing_depth)
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)
Ocean grid type. See mom_grid for details.
Provides the ocean grid type.
integer function, public advection_test_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...
logical function, public register_advection_test_tracer(HI, GV, param_file, CS, tr_Reg, restart_CS)
subroutine, public advection_test_tracer_end(CS)
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.
subroutine, public initialize_advection_test_tracer(restart, day, G, GV, h, diag, OBC, CS, sponge_CSp, diag_to_Z_CSp)
Controls where open boundary conditions are applied.
subroutine, public advection_test_tracer_surface_state(state, h, G, CS)
subroutine, public mom_error(level, message, all_print)