33 implicit none ;
private
35 #include <MOM_memory.h>
38 public register_rgc_tracer, initialize_rgc_tracer
39 public rgc_tracer_column_physics, rgc_tracer_end
41 integer,
parameter :: ntr = 1
45 logical :: coupled_tracers = .false.
46 character(len = 200) :: tracer_ic_file
47 type(time_type),
pointer :: time
49 real,
pointer :: tr(:,:,:,:) => null()
50 real,
pointer :: tr_aux(:,:,:,:) => null()
51 real :: land_val(ntr) = -1.0
56 logical :: mask_tracers
66 function register_rgc_tracer(HI, GV, param_file, CS, tr_Reg, restart_CS)
76 character(len=80) :: name, longname
78 #include "version_variable.h"
79 character(len=40) :: mdl =
"RGC_tracer"
80 character(len=200) :: inputdir
81 real,
pointer :: tr_ptr(:,:,:) => null()
82 logical :: register_rgc_tracer
83 integer :: isd, ied, jsd, jed, nz, m
84 isd = hi%isd ; ied = hi%ied ; jsd = hi%jsd ; jed = hi%jed ; nz = gv%ke
86 if (
associated(cs))
then
87 call mom_error(warning,
"RGC_register_tracer called with an "// &
88 "associated control structure.")
95 call get_param(param_file, mdl,
"RGC_TRACER_IC_FILE", cs%tracer_IC_file, &
96 "The name of a file from which to read the initial \n"//&
97 "conditions for the RGC tracers, or blank to initialize \n"//&
98 "them internally.", default=
" ")
99 if (len_trim(cs%tracer_IC_file) >= 1)
then
100 call get_param(param_file, mdl,
"INPUTDIR", inputdir, default=
".")
101 inputdir = slasher(inputdir)
102 cs%tracer_IC_file = trim(inputdir)//trim(cs%tracer_IC_file)
103 call log_param(param_file, mdl,
"INPUTDIR/RGC_TRACER_IC_FILE", &
106 call get_param(param_file, mdl,
"SPONGE", cs%use_sponge, &
107 "If true, sponges may be applied anywhere in the domain. \n"//&
108 "The exact location and properties of those sponges are \n"//&
109 "specified from MOM_initialization.F90.", default=.false.)
111 call get_param(param_file, mdl,
"LENLAT", cs%lenlat, &
112 "The latitudinal or y-direction length of the domain", &
113 fail_if_missing=.true., do_not_log=.true.)
115 call get_param(param_file, mdl,
"LENLON", cs%lenlon, &
116 "The longitudinal or x-direction length of the domain", &
117 fail_if_missing=.true., do_not_log=.true.)
119 call get_param(param_file, mdl,
"CONT_SHELF_LENGTH", cs%CSL, &
120 "The length of the continental shelf (x dir, km).", &
123 call get_param(param_file, mdl,
"LENSPONGE", cs%lensponge, &
124 "The length of the sponge layer (km).", &
127 allocate(cs%tr(isd:ied,jsd:jed,nz,ntr)) ; cs%tr(:,:,:,:) = 0.0
128 if (cs%mask_tracers)
then
129 allocate(cs%tr_aux(isd:ied,jsd:jed,nz,ntr)) ; cs%tr_aux(:,:,:,:) = 0.0
133 if (m < 10)
then ;
write(name,
'("tr_RGC",I1.1)') m
134 else ;
write(name,
'("tr_RGC",I2.2)') m ;
endif
135 write(longname,
'("Concentration of RGC Tracer ",I2.2)') m
136 cs%tr_desc(m) = var_desc(name, units=
"kg kg-1", longname=longname, caller=mdl)
139 tr_ptr => cs%tr(:,:,:,m)
141 call register_tracer(tr_ptr, tr_reg, param_file, hi, gv, &
142 name=name, longname=longname, units=
"kg kg-1", &
143 registry_diags=.true., flux_units=
"kg/s", &
144 restart_cs=restart_cs)
148 register_rgc_tracer = .true.
149 end function register_rgc_tracer
153 subroutine initialize_rgc_tracer(restart, day, G, GV, h, diag, OBC, CS, &
154 layer_CSp, sponge_CSp)
158 logical,
intent(in) :: restart
160 type(time_type),
target,
intent(in) :: day
161 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
163 type(
diag_ctrl),
target,
intent(in) :: diag
173 real,
allocatable :: temp(:,:,:)
174 real,
pointer,
dimension(:,:,:) :: &
175 obc_tr1_u => null(), &
179 character(len=16) :: name
180 character(len=72) :: longname
181 character(len=48) :: units
182 character(len=48) :: flux_units
184 real,
pointer :: tr_ptr(:,:,:) => null()
190 real :: e(szk_(g)+1), e_top, e_bot, d_tr
191 integer :: i, j, k, is, ie, js, je, isd, ied, jsd, jed, nz, m
192 integer :: isdb, iedb, jsdb, jedb
195 if (.not.
associated(cs))
return
196 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
197 isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
198 isdb = g%IsdB ; iedb = g%IedB ; jsdb = g%JsdB ; jedb = g%JedB
199 h_neglect = gv%H_subroundoff
204 if (.not.restart)
then
205 if (len_trim(cs%tracer_IC_file) >= 1)
then
207 if (.not.
file_exists(cs%tracer_IC_file, g%Domain)) &
208 call mom_error(fatal,
"RGC_initialize_tracer: Unable to open "// &
211 call query_vardesc(cs%tr_desc(m), name, caller=
"initialize_RGC_tracer")
212 call read_data(cs%tracer_IC_file, trim(name), &
213 cs%tr(:,:,:,m), domain=g%Domain%mpp_domain)
217 do k=1,nz ;
do j=js,je ;
do i=is,ie
219 enddo ;
enddo ;
enddo
222 do j=js,je ;
do i=is,ie
224 if (g%geoLonT(i,j) <= (cs%CSL))
then
232 if ( cs%use_sponge )
then
236 if (
associated(sponge_csp))
then
237 nzdata = get_ale_sponge_nz_data(sponge_csp)
239 allocate(temp(g%isd:g%ied,g%jsd:g%jed,nzdata))
240 do k=1,nzdata ;
do j=js,je ;
do i=is,ie
241 if (g%geoLonT(i,j) >= (cs%lenlon - cs%lensponge) .AND. g%geoLonT(i,j) <= cs%lenlon)
then
247 tr_ptr => cs%tr(:,:,:,m)
253 elseif (
associated(layer_csp))
then
255 allocate(temp(g%isd:g%ied,g%jsd:g%jed,nz))
256 do k=1,nz ;
do j=js,je ;
do i=is,ie
257 if (g%geoLonT(i,j) >= (cs%lenlon - cs%lensponge) .AND. g%geoLonT(i,j) <= cs%lenlon)
then
262 tr_ptr => cs%tr(:,:,:,m)
263 call set_up_sponge_field(temp, tr_ptr, g, nz, layer_csp)
268 call mom_error(fatal,
"RGC_initialize_tracer: "// &
269 "The pointer to sponge_CSp must be associated if SPONGE is defined.")
273 end subroutine initialize_rgc_tracer
278 subroutine rgc_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, G, GV, CS, &
279 evap_CFL_limit, minimum_forcing_depth)
282 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
284 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
286 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
290 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
294 type(
forcing),
intent(in) :: fluxes
296 real,
intent(in) :: dt
298 real,
optional,
intent(in) :: evap_cfl_limit
300 real,
optional,
intent(in) :: minimum_forcing_depth
307 real :: c1(szi_(g),szk_(g))
308 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)) :: h_work
309 real :: in_flux(szi_(g),szj_(g),2)
311 integer :: i, j, k, is, ie, js, je, nz, m
312 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
314 if (.not.
associated(cs))
return
318 do j=js,je ;
do i=is,ie
320 if (g%geoLonT(i,j) <= (cs%CSL))
then
325 if (
present(evap_cfl_limit) .and.
present(minimum_forcing_depth))
then
327 do k=1,nz ;
do j=js,je ;
do i=is,ie
328 h_work(i,j,k) = h_old(i,j,k)
329 enddo ;
enddo ; enddo;
330 call applytracerboundaryfluxesinout(g, gv, cs%tr(:,:,:,m) , dt, fluxes, h_work, &
331 evap_cfl_limit, minimum_forcing_depth, in_flux(:,:,m))
333 call tracer_vertdiff(h_work, ea, eb, dt, cs%tr(:,:,:,m), g, gv)
337 call tracer_vertdiff(h_old, ea, eb, dt, cs%tr(:,:,:,m), g, gv)
341 end subroutine rgc_tracer_column_physics
343 subroutine rgc_tracer_end(CS)
347 if (
associated(cs))
then
348 if (
associated(cs%tr))
deallocate(cs%tr)
351 end subroutine rgc_tracer_end