47 use mom_io, only : read_data
51 implicit none ;
private 53 #include <MOM_memory.h> 59 function tracer_z_init(tr, h, filename, tr_name, G, missing_val, land_val)
60 logical :: tracer_Z_init
62 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(out) :: tr
63 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h
64 character(len=*),
intent(in) :: filename, tr_name
66 real,
optional,
intent(in) :: missing_val
67 real,
optional,
intent(in) :: land_val
79 integer,
save :: init_calls = 0
81 #include "version_variable.h" 82 character(len=40) :: mdl =
"MOM_tracer_Z_init" 83 character(len=256) :: mesg
85 real,
allocatable,
dimension(:,:,:) :: &
87 real,
allocatable,
dimension(:) :: &
101 real :: htot(szi_(g))
106 logical :: has_edges, use_missing, zero_surface
107 character(len=80) :: loc_msg
108 integer :: k_top, k_bot, k_bot_prev
109 integer :: i, j, k, kz, is, ie, js, je, nz, nz_in
110 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
112 landval = 0.0 ;
if (
present(land_val)) landval = land_val
114 zero_surface = .false.
116 use_missing = .false.
117 if (
present(missing_val))
then 118 use_missing = .true. ; missing = missing_val
123 call read_z_edges(filename, tr_name, z_edges, nz_in, has_edges, use_missing, missing)
125 tracer_z_init = .false.
129 allocate(tr_in(g%isd:g%ied,g%jsd:g%jed,nz_in)) ; tr_in(:,:,:) = 0.0
130 allocate(tr_1d(nz_in)) ; tr_1d(:) = 0.0
131 call read_data(filename, tr_name, tr_in(:,:,:), domain=g%Domain%mpp_domain)
135 if (
present(missing_val))
then 136 do j=js,je ;
do i=is,ie
137 if (g%mask2dT(i,j) == 0.0)
then 138 tr_in(i,j,1) = landval
139 elseif (abs(tr_in(i,j,1) - missing_val) <= 1e-6*abs(missing_val))
then 140 write(loc_msg,
'(f7.2," N ",f7.2," E")') g%geoLatT(i,j), g%geoLonT(i,j)
141 if (zero_surface)
then 142 call mom_error(warning,
"tracer_Z_init: Missing value of "// &
143 trim(tr_name)//
" found in an ocean point at "//trim(loc_msg)// &
144 " in "//trim(filename) )
147 call mom_error(fatal,
"tracer_Z_init: Missing value of "// &
148 trim(tr_name)//
" found in an ocean point at "//trim(loc_msg)// &
149 " in "//trim(filename) )
153 do k=2,nz_in ;
do j=js,je ;
do i=is,ie
154 if (abs(tr_in(i,j,k) - missing_val) <= 1e-6*abs(missing_val)) &
155 tr_in(i,j,k) = tr_in(i,j,k-1)
156 enddo ;
enddo ;
enddo 159 allocate(wt(nz_in+1)) ;
allocate(z1(nz_in+1)) ;
allocate(z2(nz_in+1))
165 do i=is,ie ; htot(i) = 0.0 ;
enddo 166 do k=1,nz ;
do i=is,ie ; htot(i) = htot(i) + h(i,j,k) ;
enddo ;
enddo 168 do i=is,ie ;
if (g%mask2dT(i,j)*htot(i) > 0.0)
then 170 dilate = (g%bathyT(i,j) - 0.0) / htot(i)
171 e(nz+1) = -g%bathyT(i,j)
172 do k=nz,1,-1 ; e(k) = e(k+1) + dilate * h(i,j,k) ;
enddo 175 do k=1,nz_in ; tr_1d(k) = tr_in(i,j,k) ;
enddo 176 k_bot = 1 ; k_bot_prev = -1
178 if (e(k+1) > z_edges(1))
then 180 elseif (e(k) < z_edges(nz_in+1))
then 181 tr(i,j,k) = tr_1d(nz_in)
184 k_bot, k_top, k_bot, wt, z1, z2)
186 if (kz /= k_bot_prev)
then 189 if ((kz < nz_in) .and. (kz > 1))
call &
193 tr(i,j,k) = wt(kz) * &
194 (tr_1d(kz) + 0.5*sl_tr*(z2(kz) + z1(kz)))
197 do kz=k_top+1,k_bot-1
198 tr(i,j,k) = tr(i,j,k) + wt(kz)*tr_1d(kz)
200 if (k_bot > k_top)
then 204 if ((kz < nz_in) .and. (kz > 1))
call &
207 tr(i,j,k) = tr(i,j,k) + wt(kz) * &
208 (tr_1d(kz) + 0.5*sl_tr*(z2(kz) + z1(kz)))
217 if ((e(k) > z_edges(1)) .and. (z_edges(nz_in+1) > e(k+1)))
then 218 tr(i,j,k) = (((e(k) - z_edges(1)) * tr_1d(1) + &
219 (z_edges(1) - z_edges(nz_in)) * tr(i,j,k)) + &
220 (z_edges(nz_in+1) - e(k+1)) * tr_1d(nz_in)) / &
222 elseif (e(k) > z_edges(1))
then 223 tr(i,j,k) = ((e(k) - z_edges(1)) * tr_1d(1) + &
224 (z_edges(1) - e(k+1)) * tr(i,j,k)) / &
226 elseif (z_edges(nz_in) > e(k+1))
then 227 tr(i,j,k) = ((e(k) - z_edges(nz_in+1)) * tr(i,j,k) + &
228 (z_edges(nz_in+1) - e(k+1)) * tr_1d(nz_in)) / &
234 do k=1,nz ; tr(i,j,k) = landval ;
enddo 240 do i=is,ie ; htot(i) = 0.0 ;
enddo 241 do k=1,nz ;
do i=is,ie ; htot(i) = htot(i) + h(i,j,k) ;
enddo ;
enddo 243 do i=is,ie ;
if (g%mask2dT(i,j)*htot(i) > 0.0)
then 245 dilate = (g%bathyT(i,j) - 0.0) / htot(i)
246 e(nz+1) = -g%bathyT(i,j)
247 do k=nz,1,-1 ; e(k) = e(k+1) + dilate * h(i,j,k) ;
enddo 250 do k=1,nz_in ; tr_1d(k) = tr_in(i,j,k) ;
enddo 253 if (e(k+1) > z_edges(1))
then 255 elseif (z_edges(nz_in) > e(k))
then 256 tr(i,j,k) = tr_1d(nz_in)
259 k_bot, k_top, k_bot, wt, z1, z2)
262 if (k_top < nz_in)
then 263 tr(i,j,k) = wt(kz)*0.5*((tr_1d(kz) + tr_1d(kz+1)) + &
264 (tr_1d(kz+1) - tr_1d(kz))*(z2(kz)+z1(kz)))
266 tr(i,j,k) = wt(kz)*tr_1d(nz_in)
268 do kz=k_top+1,k_bot-1
269 tr(i,j,k) = tr(i,j,k) + wt(kz)*0.5*(tr_1d(kz) + tr_1d(kz+1))
271 if (k_bot > k_top)
then 273 tr(i,j,k) = tr(i,j,k) + wt(kz)*0.5*((tr_1d(kz) + tr_1d(kz+1)) + &
274 (tr_1d(kz+1) - tr_1d(kz))*(z2(kz)+z1(kz)))
279 if ((e(k) > z_edges(1)) .and. (z_edges(nz_in) > e(k+1)))
then 280 tr(i,j,k) = (((e(k) - z_edges(1)) * tr_1d(1) + &
281 (z_edges(1) - z_edges(nz_in)) * tr(i,j,k)) + &
282 (z_edges(nz_in) - e(k+1)) * tr_1d(nz_in)) / &
284 elseif (e(k) > z_edges(1))
then 285 tr(i,j,k) = ((e(k) - z_edges(1)) * tr_1d(1) + &
286 (z_edges(1) - e(k+1)) * tr(i,j,k)) / &
288 elseif (z_edges(nz_in) > e(k+1))
then 289 tr(i,j,k) = ((e(k) - z_edges(nz_in)) * tr(i,j,k) + &
290 (z_edges(nz_in) - e(k+1)) * tr_1d(nz_in)) / &
296 do k=1,nz ; tr(i,j,k) = landval ;
enddo 301 deallocate(tr_in) ;
deallocate(tr_1d) ;
deallocate(z_edges)
302 deallocate(wt) ;
deallocate(z1) ;
deallocate(z2)
304 tracer_z_init = .true.
309 subroutine read_z_edges(filename, tr_name, z_edges, nz_out, has_edges, &
310 use_missing, missing)
311 character(len=*),
intent(in) :: filename, tr_name
312 real,
allocatable,
dimension(:),
intent(out) :: z_edges
313 integer,
intent(out) :: nz_out
314 logical,
intent(out) :: has_edges
315 logical,
intent(inout) :: use_missing
316 real,
intent(inout) :: missing
330 character(len=32) :: mdl
331 character(len=120) :: dim_name, edge_name, tr_msg, dim_msg
333 integer :: ncid, status, intid, tr_id, layid, k
334 integer :: nz_edge, ndim, tr_dim_ids(nf90_max_var_dims)
336 mdl =
"MOM_tracer_Z_init read_Z_edges: " 337 tr_msg = trim(tr_name)//
" in "//trim(filename)
339 status = nf90_open(filename, nf90_nowrite, ncid);
340 if (status /= nf90_noerr)
then 341 call mom_error(warning,mdl//
" Difficulties opening "//trim(filename)//&
342 " - "//trim(nf90_strerror(status)))
346 status = nf90_inq_varid(ncid, tr_name, tr_id)
347 if (status /= nf90_noerr)
then 348 call mom_error(warning,mdl//
" Difficulties finding variable "//&
349 trim(tr_msg)//
" - "//trim(nf90_strerror(status)))
350 nz_out = -1 ; status = nf90_close(ncid) ;
return 352 status = nf90_inquire_variable(ncid, tr_id, ndims=ndim, dimids=tr_dim_ids)
353 if (status /= nf90_noerr)
then 354 call mom_error(warning,mdl//
" cannot inquire about "//trim(tr_msg))
355 elseif ((ndim < 3) .or. (ndim > 4))
then 356 call mom_error(warning,mdl//
" "//trim(tr_msg)//&
357 " has too many or too few dimensions.")
358 nz_out = -1 ; status = nf90_close(ncid) ;
return 361 if (.not.use_missing)
then 363 status = nf90_get_att(ncid, tr_id,
"missing_value", missing)
364 if (status /= nf90_noerr) use_missing = .true.
368 status = nf90_inquire_dimension(ncid, tr_dim_ids(3), dim_name, len=nz_out)
369 if (status /= nf90_noerr)
then 370 call mom_error(warning,mdl//
" cannot inquire about dimension(3) of "//&
374 dim_msg = trim(dim_name)//
" in "//trim(filename)
375 status = nf90_inq_varid(ncid, dim_name, layid)
376 if (status /= nf90_noerr)
then 377 call mom_error(warning,mdl//
" Difficulties finding variable "//&
378 trim(dim_msg)//
" - "//trim(nf90_strerror(status)))
379 nz_out = -1 ; status = nf90_close(ncid) ;
return 382 status = nf90_get_att(ncid, layid,
"edges", edge_name)
383 if (status /= nf90_noerr)
then 384 call mom_mesg(mdl//
" "//trim(dim_msg)//&
385 " has no readable edges attribute - "//trim(nf90_strerror(status)))
389 status = nf90_inq_varid(ncid, edge_name, intid)
390 if (status /= nf90_noerr)
then 391 call mom_error(warning,mdl//
" Difficulties finding edge variable "//&
392 trim(edge_name)//
" in "//trim(filename)//
" - "//trim(nf90_strerror(status)))
397 nz_edge = nz_out ;
if (has_edges) nz_edge = nz_out+1
398 allocate(z_edges(nz_edge)) ; z_edges(:) = 0.0
400 if (nz_out < 1)
return 404 dim_msg = trim(edge_name)//
" in "//trim(filename)
405 status = nf90_get_var(ncid, intid, z_edges)
406 if (status /= nf90_noerr)
then 407 call mom_error(warning,mdl//
" Difficulties reading variable "//&
408 trim(dim_msg)//
" - "//trim(nf90_strerror(status)))
409 nz_out = -1 ; status = nf90_close(ncid) ;
return 412 status = nf90_get_var(ncid, layid, z_edges)
413 if (status /= nf90_noerr)
then 414 call mom_error(warning,mdl//
" Difficulties reading variable "//&
415 trim(dim_msg)//
" - "//trim(nf90_strerror(status)))
416 nz_out = -1 ; status = nf90_close(ncid) ;
return 420 status = nf90_close(ncid)
421 if (status /= nf90_noerr)
call mom_error(warning, mdl// &
422 " Difficulties closing "//trim(filename)//
" - "//trim(nf90_strerror(status)))
426 if (z_edges(1) < z_edges(2))
then 427 do k=1,nz_edge ; z_edges(k) = -z_edges(k) ;
enddo 431 do k=2,nz_edge ;
if (z_edges(k) >= z_edges(k-1)) monotonic = .false. ;
enddo 432 if (.not.monotonic) &
433 call mom_error(warning,mdl//
" "//trim(dim_msg)//
" is not monotonic.")
subroutine, public find_limited_slope(val, e, slope, k)
This subroutine determines a limited slope for val to be advected with a piecewise limited scheme...
logical function, public tracer_z_init(tr, h, filename, tr_name, G, missing_val, land_val)
subroutine, public find_overlap(e, Z_top, Z_bot, k_max, k_start, k_top, k_bot, wt, z1, z2)
This subroutine determines the layers bounded by interfaces e that overlap with the depth range betwe...
Ocean grid type. See mom_grid for details.
Provides the ocean grid type.
This module contains I/O framework code.
logical function, public is_root_pe()
subroutine, public mom_mesg(message, verb, all_print)
subroutine read_z_edges(filename, tr_name, z_edges, nz_out, has_edges, use_missing, missing)
subroutine, public mom_error(level, message, all_print)