2 ! Routines for setting upper boundary values for :
3 ! o3, no, no2, hno3, ch4, co, n2o and n2o5
4 ! From the default pressure level of 50 mb to the top level of the model,
5 ! the mixing ratio was set to a value from the monthly climatology
6 ! which varied only in latitude (from ub_vals_moz3.nc file).
7 ! Between the tropopause level and the default pressure level of 50 mb,
8 ! the mixing ratio was relaxed with a 10-day relaxation factor.
9 ! The tropopause level was determined by the primary routine of
10 ! the subroutine tropopause_twmo and the backup routine of
11 ! the subroutine tropopause_climate (using data from clim_p_trop.nc file).
14 ! Adopted from module mo_fstrat of CAM-Chem
15 ! and put into the current format by Jeff Lee, Feb. 2011
17 module module_upper_bc_driver
23 public :: upper_bc_init
24 public :: upper_bc_driver
28 real, parameter :: mb2Pa = 100.
29 real, parameter :: vmr2ppmv = 1.e6
31 real, parameter :: tau_relax = 864000. ! 10 days relaxation
33 real :: fixed_ubc_press
38 integer :: ub_month_n ! # of month in ubc file
39 integer :: ub_lev_n ! # of lev in ubc file
40 integer :: ub_lat_n ! # of lat in ubc file
41 integer :: ub_species_n ! # of species in ubc file
42 integer :: ub_nchar_n ! # of nchar in ubc file
43 integer :: max_dom ! wrf domain count
45 real , allocatable :: ub_p_m(:) ! ubc midpoint levels pressure(Pa)
46 real , allocatable :: ub_p_e(:) ! ubc edge levels pressure(Pa)
47 real , allocatable :: ub_vmr(:,:,:,:) ! values of vmr in ubc file
48 real , allocatable :: ub_lat(:) ! values of lat in ubc file
49 integer , allocatable :: ub_map(:) ! species indices for ubc species
51 integer :: nox_ndx = -1
52 integer :: ox_ndx = -1
54 !----------------------------------------------------
56 !----------------------------------------------------
59 real, pointer :: vmr(:,:,:,:,:) ! values of vmr in ubc file
60 logical :: is_allocated
61 end type chem_upper_bc
63 type(chem_upper_bc), private, allocatable :: upper_bc(:)
67 !==========================================================================
68 subroutine upper_bc_driver( id, dtstep, current_date_char, &
69 chem, p_phy, p8w, tropo_lev, &
70 ids, ide, jds, jde, kds, kde, &
71 ims, ime, jms, jme, kms, kme, &
72 its, ite, jts, jte, kts, kte )
74 use module_state_description
75 use module_model_constants
77 !----------------------------------------------------
79 !----------------------------------------------------
80 integer, intent(in) :: id, &
81 ids,ide, jds,jde, kds,kde, &
82 ims,ime, jms,jme, kms,kme, &
83 its,ite, jts,jte, kts,kte
85 real, dimension(ims:ime, kms:kme, jms:jme ), &
86 intent(in) :: p_phy, & ! p at mid-level (Pa)
87 p8w ! p at interface (Pa)
88 integer, dimension(ims:ime, jms:jme ), &
89 intent(in) :: tropo_lev ! tropopause level
91 real, intent(in) :: dtstep
93 CHARACTER (LEN=256) , intent(in) :: current_date_char
95 real, dimension(ims:ime,kms:kme,jms:jme,num_chem ), &
98 !----------------------------------------------------
100 !----------------------------------------------------
101 integer :: next, last
106 integer :: i, j, k, m, n
107 integer :: ku(kts:kte)
108 integer :: kl(kts:kte)
109 integer :: del_p(kts:kte)
113 real :: nox_ubc, xno, xno2, rno
115 real, allocatable :: table_ox(:)
116 real, allocatable :: p8w_temp(:)
117 real, allocatable :: chem_temp(:)
118 character(len=132) :: message
120 !-----------------------------------------------------------------------
121 ! tile dimensions, needed for nest domains!!
122 !-------------------------------------------
123 iend = min(ite,ide-1)
124 jend = min(jte,jde-1)
126 !------------------------------------------------------------------------
127 !... setup for time interpolation
128 !------------------------------------------------------------------------
129 call get_time_interp_factors ( current_date_char, last, next, del_time )
131 !--------------------------------------------------------
132 ! ... setup for ox conserving interp
133 !--------------------------------------------------------
134 if( ox_ndx > 0 ) then
135 allocate( table_ox(ub_lev_n-2),stat=astat )
136 if( astat /= 0 ) then
137 write(message,*) 'upper_bc_driver: table_ox allocation error = ',astat
138 CALL wrf_message( trim(message) )
148 !--------------------------------------------------------
149 ! setup for the pressure interpolation
150 !--------------------------------------------------------
152 do k = kte,kts,-1 ! from top to bottom
154 if( p_phy(i,k,j) <= ub_p_m(1) ) then
158 else if( p_phy(i,k,j) >= ub_p_m(ub_lev_n) ) then
163 do kk = 2,ub_lev_n ! from top to bottom of ub_p_m
164 if( p_phy(i,k,j) <= ub_p_m(kk) ) then
167 del_p(k) = log( p_phy(i,k,j)/ub_p_m(kl(k)) ) &
168 / log( ub_p_m(ku(k))/ub_p_m(kl(k)) )
175 !--------------------------------------------------------
176 ! find max level less than fixed_ubc_press (default 50 mb)
177 ! fixed UB vals from top of model to this level
178 !--------------------------------------------------------
180 if( p_phy(i,kte,j) > fixed_ubc_press ) then
183 do kmax = kte,kts+1,-1 ! from top to bottom
184 if( p_phy(i,kmax,j) > fixed_ubc_press ) then
191 !--------------------------------------------------------
192 ! above fixed_ubc_press (default is 50 mb),
193 ! set the mixing ratios as fixed values
194 !--------------------------------------------------------
196 do m = 1,ub_species_n
199 if( ub_map(m) > 0 .and. kmax <= kte ) then
200 !-----------------------------------------------------------
202 !-----------------------------------------------------------
203 if( m == ox_ndx ) then
204 table_ox(1:ub_lev_n-2) = & ! from top to bottom
205 upper_bc(id)%vmr(i,j,m,last,2:ub_lev_n-1) &
206 + (upper_bc(id)%vmr(i,j,m,next,2:ub_lev_n-1) &
207 - upper_bc(id)%vmr(i,j,m,last,2:ub_lev_n-1))*del_time
211 allocate ( p8w_temp (km+1) )
212 allocate ( chem_temp(km) )
213 !-----------------------------------------------------------
214 ! upper_bc_rebin requires "top-down" ordering
215 !-----------------------------------------------------------
216 p8w_temp (1:km+1) = p8w (i,kte:kmax-1:-1,j)
218 call upper_bc_rebin( ub_lev_n-2, km, ub_p_e, p8w_temp, &
219 table_ox, chem_temp )
221 chem(i,kmax:kte,j,p_o3) = chem_temp(km:1:-1)
223 deallocate( p8w_temp )
224 deallocate( chem_temp )
228 !-----------------------------------------------------------
230 !-----------------------------------------------------------
232 do k = kte,kmax,-1 ! from top to bottom
234 pint_vals(1) = upper_bc(id)%vmr(i,j,m,last,kl(k)) &
235 + (upper_bc(id)%vmr(i,j,m,last,ku(k)) &
236 - upper_bc(id)%vmr(i,j,m,last,kl(k)))*del_p(k)
237 pint_vals(2) = upper_bc(id)%vmr(i,j,m,next,kl(k)) &
238 + (upper_bc(id)%vmr(i,j,m,next,ku(k)) &
239 - upper_bc(id)%vmr(i,j,m,next,kl(k)))*del_p(k)
241 !-----------------------------------------------------------
242 ! others: hno3, ch4, co, n2o, n2o5
243 !-----------------------------------------------------------
244 if( m /= nox_ndx ) then
245 chem(i,k,j,ub_map(m)) = pint_vals(1) &
246 + (pint_vals(2) - pint_vals(1))*del_time
247 !-----------------------------------------------------------
249 !-----------------------------------------------------------
251 nox_ubc = pint_vals(1) + del_time * (pint_vals(2) - pint_vals(1))
252 if( p_no >= param_first_scalar ) then
253 xno = chem(i,k,j,p_no)
258 if( p_no2 >= param_first_scalar ) then
259 xno2 = chem(i,k,j,p_no2)
264 if( xno > 0. .or. xno2 > 0.) then
265 rno = xno / (xno + xno2)
268 if( p_no >= param_first_scalar ) then
269 chem(i,k,j,p_no) = rno * nox_ubc
271 if( p_no2 >= param_first_scalar ) then
272 chem(i,k,j,p_no2) = (1. - rno) * nox_ubc
281 if( tropo_lev(i,j) > 0 .and. tropo_lev(i,j) < kmax ) then
282 !--------------------------------------------------------
283 !... relax lower stratosphere to extended ubc
284 ! check to make sure ubc is not being imposed too low
285 ! lev_relax = lowest model level (highest pressure)
286 ! in which to relax to ubc
287 !--------------------------------------------------------
288 lev_relax = tropo_lev(i,j)
290 do while( p_phy(i,lev_relax,j) > ub_p_m(ub_lev_n) ) ! ub_p_m(ub_lev_n)= 440 mb
291 lev_relax = lev_relax + 1 ! move level upward
294 if( lev_relax /= tropo_lev(i,j) ) then
295 write(message,*) 'upper_bc_driver:Warning,raised ubc: at j,i,= ',j,i
296 call wrf_message( trim(message) )
297 write(message,*) 'from ', tropo_lev(i,j),nint(p_phy(i,tropo_lev(i,j)-1,j)/mb2pa),' mb'
298 call wrf_message( trim(message) )
299 write(message,*) 'to ', lev_relax, nint(p_phy(i,lev_relax,j) /mb2pa),' mb'
300 call wrf_message( trim(message) )
304 do m = 1,ub_species_n
306 if( ub_map(m) > 0 ) then
307 lev_loop_b: do k = kmax-1,lev_relax,-1 ! from top to bottom
309 pint_vals(1) = upper_bc(id)%vmr(i,j,m,last,kl(k)) &
310 + (upper_bc(id)%vmr(i,j,m,last,ku(k)) &
311 - upper_bc(id)%vmr(i,j,m,last,kl(k)))*del_p(k)
312 pint_vals(2) = upper_bc(id)%vmr(i,j,m,next,kl(k)) &
313 + (upper_bc(id)%vmr(i,j,m,next,ku(k)) &
314 - upper_bc(id)%vmr(i,j,m,next,kl(k)))*del_p(k)
316 vmr_relax = pint_vals(1) &
317 + (pint_vals(2) - pint_vals(1))*del_time
319 if( m /= nox_ndx ) then
320 chem(i,k,j,ub_map(m)) = chem(i,k,j,ub_map(m)) &
321 + (vmr_relax - chem(i,k,j,ub_map(m))) * fac_relax
323 if( p_no >= param_first_scalar ) then
324 xno = chem(i,k,j,p_no)
329 if( p_no2 >= param_first_scalar ) then
330 xno2 = chem(i,k,j,p_no2)
335 if( xno > 0. .or. xno2 > 0. ) then
336 rno = xno / (xno + xno2)
340 nox_ubc = nox_ubc + (vmr_relax - nox_ubc) * fac_relax
342 if( p_no >= param_first_scalar ) then
343 chem(i,k,j,p_no) = rno * nox_ubc
346 if( p_no2 >= param_first_scalar ) then
347 chem(i,k,j,p_no2)= (1. - rno) * nox_ubc
352 end do species_loop_a
359 if( allocated( table_ox ) ) then
360 deallocate( table_ox )
363 end subroutine upper_bc_driver
365 !===========================================================================
367 subroutine upper_bc_init(id, xlat, dt, config_flags, &
368 ids,ide, jds,jde, kds,kde, &
369 ims,ime, jms,jme, kms,kme, &
370 its,ite, jts,jte, kts,kte )
371 !---------------------------------------------------------------------
372 ! ... new initialization routine for upper boundary condition
373 !---------------------------------------------------------------------
375 use module_domain ! needed for p_co, p_o3....
376 use module_state_description, only : param_first_scalar
377 use module_configure, only : grid_config_rec_type
381 !---------------------------------------------------------------------
382 ! ... dummy arguments
383 !---------------------------------------------------------------------
384 integer, intent(in) :: id, &
385 ids,ide, jds,jde, kds,kde, &
386 ims,ime, jms,jme, kms,kme, &
387 its,ite, jts,jte, kts,kte
388 real, intent(in) :: dt
389 real, intent(in) :: xlat(ims:ime, jms:jme) ! unit: degree
390 type(grid_config_rec_type), intent(in) :: config_flags
392 !---------------------------------------------------------------------
393 ! ... local variables
394 !---------------------------------------------------------------------
404 integer :: dimid_month
405 integer :: dimid_species
408 character(len=132) :: message
409 character(len=128) :: err_msg
410 character(len=64) :: filename
411 character(len=3) :: id_num
412 character(len=25), allocatable :: ub_specname(:)
414 character(len=80) :: attribute
418 integer, allocatable :: lat_interp(:,:)
419 real, allocatable :: lat_del(:,:)
421 integer :: i, j, k, m
425 LOGICAL , EXTERNAL :: wrf_dm_on_monitor
426 !-------------------------------------------------------------------------
431 call wrf_message( 'upper_bc_init: requires netcdf' )
435 !-------------------------------------
436 !... note: grid%XLAT(ide,:) =0.
437 !... note: grid%XLONG(:,jde) =0.
438 !... => iend = min(ite,ide-1)
439 ! jend = min(jte,jde-1)
440 !-------------------------------------
442 iend = min(ite,ide-1)
443 jend = min(jte,jde-1)
445 !---------------------------------------------------------------------
446 ! ... allocate chem_upper_bc type
447 !---------------------------------------------------------------------
448 if( id == 1 .and. .not. allocated(upper_bc) ) then
449 CALL nl_get_max_dom( 1,max_dom )
451 allocate( upper_bc(max_dom),stat=astat )
452 if( astat /= 0 ) then
453 CALL wrf_message( 'upper_bc_init: failed to allocate upper_bc' )
457 upper_bc(:)%is_allocated = .false.
460 upper_bc_allocated : &
461 if( .not. upper_bc(id)%is_allocated ) then
462 !---------------------------------------------------------------------
463 !... allocate upper_bc type
464 !--------------------------------------------------------------------
469 IF( wrf_dm_on_monitor() ) THEN
470 write(id_num,'(i3)') 100+id
471 write(message,*) 'upper_bc_init: intializing domain ' // id_num(2:3)
472 CALL wrf_message( trim(message) )
474 !---------------------------------------------------------------------
475 ! ... open upper_bc netcdf file
476 !---------------------------------------------------------------------
477 filename = config_flags%fixed_ubc_inname
478 if( filename == ' ' ) then
479 call wrf_message( 'upper_bc_init: input filename not specified in namelist' )
483 err_msg = 'upper_bc_init: failed to open file ' // trim(filename)
484 call handle_ncerr( nf_open( trim(filename), nf_noclobber, ncid ), trim(err_msg) )
485 write(message,*) 'upper_bc_init: id, open filename= ',id, filename
486 CALL wrf_message( trim(message) )
487 !---------------------------------------------------------------------
489 !---------------------------------------------------------------------
490 err_msg = 'upper_bc_init: failed to get month id'
491 call handle_ncerr( nf_inq_dimid( ncid, 'month', dimid_month ), trim(err_msg) )
492 err_msg = 'upper_bc_init: failed to get month'
493 call handle_ncerr( nf_inq_dimlen( ncid, dimid_month, ub_month_n ), trim(err_msg) )
495 err_msg = 'upper_bc_init: failed to get lat id'
496 call handle_ncerr( nf_inq_dimid( ncid, 'lat', dimid_lat ), trim(err_msg) )
497 err_msg = 'upper_bc_init: failed to get lat'
498 call handle_ncerr( nf_inq_dimlen( ncid, dimid_lat, ub_lat_n ), trim(err_msg) )
500 err_msg = 'upper_bc_init: failed to get lev id'
501 call handle_ncerr( nf_inq_dimid( ncid, 'lev', dimid_lev ), trim(err_msg) )
502 err_msg = 'upper_bc_init: failed to get lev'
503 call handle_ncerr( nf_inq_dimlen( ncid, dimid_lev, ub_lev_n ), trim(err_msg) )
505 err_msg = 'upper_bc_init: failed to get species id'
506 call handle_ncerr( nf_inq_dimid( ncid, 'species', dimid_species ), trim(err_msg) )
507 err_msg = 'upper_bc_init: failed to get species'
508 call handle_ncerr( nf_inq_dimlen( ncid, dimid_species, ub_species_n ), trim(err_msg) )
510 err_msg = 'upper_bc_init: failed to get nchar id'
511 call handle_ncerr( nf_inq_dimid( ncid, 'nchar', dimid(1) ), trim(err_msg) )
512 err_msg = 'upper_bc_init: failed to get nchar'
513 call handle_ncerr( nf_inq_dimlen( ncid, dimid(1), ub_nchar_n ), trim(err_msg) )
516 !---------------------------------------------------------------------
517 ! ... bcast the dimensions
518 !---------------------------------------------------------------------
520 CALL wrf_dm_bcast_integer ( ub_month_n , 1 )
521 CALL wrf_dm_bcast_integer ( ub_lat_n , 1 )
522 CALL wrf_dm_bcast_integer ( ub_lev_n , 1 )
523 CALL wrf_dm_bcast_integer ( ub_species_n , 1 )
524 CALL wrf_dm_bcast_integer ( ub_nchar_n , 1 )
526 !---------------------------------------------------------------------
527 ! ... allocate module arrays
528 !---------------------------------------------------------------------
529 allocate( ub_lat(ub_lat_n), stat=astat )
530 if( astat /= 0 ) then
531 call wrf_message( 'upper_bc_init: failed to allocate ub_lat' )
535 allocate( ub_vmr(ub_lat_n,ub_species_n,ub_month_n,ub_lev_n), stat=astat )
536 if( astat /= 0 ) then
537 call wrf_message( 'upper_bc_init: failed to allocate ub_vmr' )
541 allocate( ub_p_m(ub_lev_n), stat=astat )
542 if( astat /= 0 ) then
543 call wrf_message( 'upper_bc_init: failed to allocate ub_p_m' )
547 allocate( ub_p_e(ub_lev_n-1), stat=astat )
548 if( astat /= 0 ) then
549 call wrf_message( 'upper_bc_init: failed to allocate ub_p_e' )
553 allocate( ub_map(ub_species_n), stat=astat )
554 if( astat /= 0 ) then
555 call wrf_message( 'upper_bc_init: failed to allocate ub_map' )
559 !---------------------------------------------------------------------
561 !---------------------------------------------------------------------
563 IF ( wrf_dm_on_monitor() ) THEN
566 err_msg = 'upper_bc_init: failed to get lev variable id'
567 call handle_ncerr( nf_inq_varid( ncid, 'lev', varid ), trim(err_msg) )
568 err_msg = 'upper_bc_init: failed to read lev variable'
569 call handle_ncerr( nf_get_var_real( ncid, varid, ub_p_m ), trim(err_msg) )
573 astat = nf_get_att_text( ncid, varid, 'units', attribute )
574 if( astat == nf_noerr )then
575 if( trim(attribute) == 'mb' .or. trim(attribute) == 'hpa' )then
576 write(message,*) 'upper_bc_init: units for lev = ',trim(attribute),'... converting to pa'
577 call wrf_message( trim(message) )
578 ub_p_m(:) = mb2Pa * ub_p_m(:)
579 else if( trim(attribute) /= 'pa' .and. trim(attribute) /= 'pa' )then
580 write(message,*) 'upper_bc_init: unknown units for lev, units=*',trim(attribute),'*'
581 call wrf_message( trim(message) )
585 write(message,*) 'upper_bc_init: warning! units attribute for lev missing, assuming mb'
586 call wrf_message( trim(message) )
587 ub_p_m(:) = mb2Pa * ub_p_m(:)
590 ! ... set values of ub_p_e
592 ub_p_e(1:ub_lev_n-1) = .5*(ub_p_m(1:ub_lev_n-1) + ub_p_m(2:ub_lev_n))
594 !---------------------------
596 err_msg = 'upper_bc_init: failed to get lat variable id'
597 call handle_ncerr( nf_inq_varid( ncid, 'lat', varid ), trim(err_msg) )
598 err_msg = 'upper_bc_init: failed to read lat variable'
599 call handle_ncerr( nf_get_var_real( ncid, varid, ub_lat ), trim(err_msg) )
601 !---------------------------
603 allocate( ub_specname(ub_species_n), stat=astat )
604 if( astat /= 0 ) then
605 call wrf_message( 'upper_bc_init: failed to allocate ub_specname' )
610 do i = 1,ub_species_n
611 start(:2) = (/ 1, i /)
612 count(:2) = (/ ub_nchar_n, 1 /)
614 ub_specname(i)(:) = ' '
616 err_msg = 'upper_bc_init: failed to get specname variable id'
617 call handle_ncerr( nf_inq_varid( ncid, 'specname', varid ), trim(err_msg) )
618 err_msg = 'upper_bc_init: failed to read ub_specname variable'
619 call handle_ncerr( nf_get_vara_text( ncid, varid, start(:2), count(:2), ub_specname(i) ), trim(err_msg) )
623 if( trim(ub_specname(i)) == 'HNO3' .and. p_hno3 >= param_first_scalar ) then
625 else if ( trim(ub_specname(i)) == 'CH4' .and. p_ch4 >= param_first_scalar ) then
627 else if ( trim(ub_specname(i)) == 'CO' .and. p_co >= param_first_scalar ) then
629 else if ( trim(ub_specname(i)) == 'N2O' .and. p_n2o >= param_first_scalar ) then
631 else if ( trim(ub_specname(i)) == 'N2O5' .and. p_n2o5 >= param_first_scalar ) then
633 else if ( trim(ub_specname(i)) == 'OX' .and. p_o3 >= param_first_scalar ) then
636 else if ( trim(ub_specname(i)) == 'NOX' .and. &
637 (p_no >= param_first_scalar .or. p_no2 >= param_first_scalar) ) then
642 if( ub_map(i) == 0 ) then
643 write(message,*) 'upper_bc_init: ubc table species ',trim(ub_specname(i)), ' not used'
644 call wrf_message( trim(message) )
648 !--------------------------
650 err_msg = 'upper_bc_init: failed to get vmr variable id'
651 call handle_ncerr( nf_inq_varid( ncid, 'vmr', varid ), trim(err_msg) )
655 err_msg = 'upper_bc_init: failed to get ndims of vmr variable'
656 call handle_ncerr( nf_inq_varndims( ncid, varid, ndims ), trim(err_msg) )
658 if( ndims /= 4 ) then
659 write(message,*) 'upper_bc_init: error! variable vmr has ndims = ',ndims,', expecting 4'
660 call wrf_message( trim(message) )
664 err_msg = 'upper_bc_init: failed to get dimid of vmr variable'
665 call handle_ncerr( nf_inq_vardimid( ncid, varid, dimid ), trim(err_msg) )
667 if( dimid(1) /= dimid_lat .or. dimid(2) /= dimid_species .or. &
668 dimid(3) /= dimid_month .or. dimid(4) /= dimid_lev )then
669 write(message,*) 'upper_bc_init: error! dimensions in wrong order for variable vmr,'// &
670 'expecting (lat,species,month,lev)'
671 call wrf_message( trim(message) )
675 !------------------------------------------------------------------
676 ! ... read in the ub mixing ratio values
677 !------------------------------------------------------------------
678 err_msg = 'upper_bc_init: failed to read vmr variable'
679 call handle_ncerr( nf_get_var_real( ncid, varid, ub_vmr ), trim(err_msg) )
681 !---------------------------------------------------------------------
682 !... close input netcdf file
683 !---------------------------------------------------------------------
684 err_msg = 'upper_bc_init: failed to close file ' // trim(filename)
685 call handle_ncerr( nf_close( ncid ), trim(err_msg) )
687 deallocate( ub_specname, stat=astat )
688 if( astat /= 0 ) then
689 write(message,*) ': failed to deallocate ub_specnmae; astat = ',astat
690 call wrf_message( trim(message) )
696 !---------------------------------------------------------------------
697 ! ... bcast the variables
698 !---------------------------------------------------------------------
700 CALL wrf_dm_bcast_integer ( nox_ndx , 1 )
701 CALL wrf_dm_bcast_integer ( ox_ndx , 1 )
703 CALL wrf_dm_bcast_integer ( ub_map, size(ub_map) )
704 CALL wrf_dm_bcast_real ( ub_p_m, size(ub_p_m) )
705 CALL wrf_dm_bcast_real ( ub_p_e, size(ub_p_e) )
706 CALL wrf_dm_bcast_real ( ub_lat, size(ub_lat) )
707 CALL wrf_dm_bcast_real ( ub_vmr, size(ub_vmr) )
709 fixed_ubc_press = config_flags%fixed_ubc_press*mb2Pa
712 upper_bc(id)%is_allocated = .true.
714 write(message,*) 'upper_bc_init: ub_vmr(1,1,1,:)'
715 call wrf_message( trim(message) )
717 write(message,'(1p,5g15.7)') ub_vmr(1,1,1,k:min(k+4,ub_lev_n))
718 call wrf_message( trim(message) )
721 !---------------------------------------------------------------------
722 ! ... allocate domain specific arrays
723 !---------------------------------------------------------------------
724 allocate( lat_del(its:iend,jts:jend), stat=astat )
725 if( astat /= 0 ) then
726 call wrf_message( 'upper_bc_init: failed to allocate lat_del' )
730 allocate( lat_interp(its:iend,jts:jend), stat=astat )
731 if( astat /= 0 ) then
732 call wrf_message( 'upper_bc_init: failed to allocate lat_interp' )
736 !------------------------------------------------------------------
737 ! ... regrid mixing ratio to model latitudes
738 !------------------------------------------------------------------
739 !-------------------------------------
740 !... get lat_del, lat_interp and lati
741 !-------------------------------------
742 call get_lat_interp_factors( id, xlat, jend, iend, &
744 lat_del, lat_interp, lati, &
745 ids,ide, jds,jde, kds,kde, &
746 ims,ime, jms,jme, kms,kme, &
747 its,ite, jts,jte, kts,kte )
749 !---------------------------------------------------------------------
750 ! ... allocate upper_bc(id) component array
751 !---------------------------------------------------------------------
752 allocate( upper_bc(id)%vmr(its:iend,jts:jend,ub_species_n,ub_month_n,ub_lev_n), stat=astat )
753 if( astat /= 0 ) then
754 call wrf_message( 'upper_bc_init: failed to allocate upper_bc(id)%vrm' )
758 !--------------------------------------------------------------------
759 !... regrid from ub_vmr to upper_bc(id)%vmr
760 !--------------------------------------------------------------------
765 upper_bc(id)%vmr(i,j,:,:,:) = ub_vmr(j1,:,:,:) + &
766 lat_del(i,j) * (ub_vmr(j2,:,:,:) - ub_vmr(j1,:,:,:))
770 !----------------------------------------------------
771 ! transform to ppm vmr
772 !----------------------------------------------------
773 upper_bc(id)%vmr(:,:,:,:,:) = upper_bc(id)%vmr(:,:,:,:,:)*vmr2ppmv
775 write(message,*) 'upper_bc_init: upper_bc(id)%vmr(its+5,jts+5,1,6,:)'
776 call wrf_message( trim(message) )
778 write(message,'(1p,5g15.7)') upper_bc(id)%vmr(its+5,jts+5,1,6,k:min(k+4,ub_lev_n))
779 call wrf_message( trim(message) )
782 !--------------------------------------------------------
783 ! ... set up the relaxation for lower stratosphere
784 !--------------------------------------------------------
785 ! ... tau_relax = relaxation timescale (in sec)
786 ! fac_relax = fractional relaxation towards ubc
788 ! 0 => ignore ubc, use model concentrations
789 !--------------------------------------------------------
791 fac_relax = 1. - exp( -real(dt)/tau_relax )
793 !--------------------------------------------------------
795 if( id == max_dom ) then
800 deallocate( lat_interp)
802 call wrf_message( ' ' )
803 write(message,*) 'upper_bc_init: DONE intialized domain ',id
804 call wrf_message( trim(message) )
805 call wrf_message( ' ' )
807 endif upper_bc_allocated
809 end subroutine upper_bc_init
811 !===========================================================================
813 subroutine handle_ncerr( ret, mes )
814 !---------------------------------------------------------------------
815 ! ... netcdf error handling routine
816 !---------------------------------------------------------------------
820 !---------------------------------------------------------------------
821 ! ... dummy arguments
822 !---------------------------------------------------------------------
823 integer, intent(in) :: ret
824 character(len=*), intent(in) :: mes
830 if( ret /= nf_noerr ) then
831 call wrf_message( trim(mes) )
832 call wrf_message( trim(nf_strerror(ret)) )
836 end subroutine handle_ncerr
838 !===========================================================================
840 subroutine get_time_interp_factors ( current_date_char, last, next, del_time)
842 use module_date_time, only : get_julgmt
846 !-----------------------------------------------------------------------------
847 ! ... dummy arguments
848 !-----------------------------------------------------------------------------
849 CHARACTER (LEN=256),intent(in) :: current_date_char
851 integer, intent(out) :: next, last
852 real, intent(out) :: del_time
853 !-----------------------------------------------------------------------------
854 ! ... local variables
855 !-----------------------------------------------------------------------------
857 integer, parameter :: day_of_year(12) = (/ 16, 45, 75, 105, 136, 166, 197, &
858 228, 258, 289, 319, 350 /)
859 INTEGER :: julyr , julday
864 !------------------------------------------------------------------------------
866 call get_julgmt ( current_date_char, julyr, julday, gmt )
868 calday = real(julday) + gmt
870 if( calday < day_of_year(1) ) then
873 del_time = (365. + calday - day_of_year(12)) &
874 / (365. + day_of_year(1) - day_of_year(12))
875 else if( calday >= day_of_year(12) ) then
878 del_time = (calday - day_of_year(12)) &
879 / (365. + day_of_year(1) - day_of_year(12))
882 if( calday >= day_of_year(m) ) then
888 del_time = (calday - day_of_year(m)) / (day_of_year(m+1) - day_of_year(m))
891 del_time = max( min( 1.,del_time ),0. )
893 end subroutine get_time_interp_factors
895 !===========================================================================
897 subroutine upper_bc_rebin( nsrc, ntrg, src_x, trg_x, src, trg )
898 !---------------------------------------------------------------
899 ! ... rebin src to trg
900 !---------------------------------------------------------------
904 !---------------------------------------------------------------
905 ! ... dummy arguments
906 !---------------------------------------------------------------
907 integer, intent(in) :: nsrc ! dimension source array
908 integer, intent(in) :: ntrg ! dimension target array
909 real, intent(in) :: src_x(nsrc+1) ! source coordinates
910 real, intent(in) :: trg_x(ntrg+1) ! target coordinates
911 real, intent(in) :: src(nsrc) ! source array
912 real, intent(out) :: trg(ntrg) ! target array
914 !---------------------------------------------------------------
915 ! ... local variables
916 !---------------------------------------------------------------
926 if( tl < src_x(nsrc+1) ) then
928 if( tl <= src_x(sil) ) then
934 if( tu <= src_x(siu) ) then
940 siu = min( siu,nsrc+1 )
943 sl = max( tl,src_x(si1) )
944 su = min( tu,src_x(si) )
945 y = y + (su - sl)*src(si1)
947 trg(i) = y/(trg_x(i+1) - trg_x(i))
953 end subroutine upper_bc_rebin
955 !===========================================================================
957 subroutine get_lat_interp_factors( id, xlat, jend, iend, &
958 from_lat_n, from_lat, &
959 lat_del, lat_interp, lati, &
960 ids, ide, jds, jde, kds, kde, &
961 ims, ime, jms, jme, kms, kme, &
962 its, ite, jts, jte, kts, kte )
964 !---------------------------------------------------------------------
965 ! ... Determine indicies and deltas for transform
966 ! Note : it is assumed that the latitude and longitude
967 ! arrays are monotonic
968 !--------------------------------------------------------------------
972 !---------------------------------------------------------------------
974 !---------------------------------------------------------------------
975 integer, intent(in) :: id, &
976 ids,ide, jds,jde, kds,kde, &
977 ims,ime, jms,jme, kms,kme, &
978 its,ite, jts,jte, kts,kte
980 real, intent(in) :: xlat(ims:ime, jms:jme) ! unit: degree
981 integer, intent(in) :: jend
982 integer, intent(in) :: iend
983 integer, intent(in) :: from_lat_n
984 real , intent(in) :: from_lat(from_lat_n)
986 integer, intent(out) :: lati
987 integer, intent(out) :: lat_interp(its:iend,jts:jend)
988 real, intent(out) :: lat_del(its:iend,jts:jend)
990 !---------------------------------------------------------------------
991 ! ... Local variables
992 !---------------------------------------------------------------------
995 real :: to_lat(jts:jend) ! values of wrf lat, 1d
1001 integer :: latl, latu
1002 real :: max_lat, min_lat
1003 logical :: from_lats_mono_pos
1008 !---------------------------------------------------------------------
1009 !... set "module" variable, converter(id)%lati
1010 !---------------------------------------------------------------------
1012 max_lat = from_lat(from_lat_n)
1013 min_lat = from_lat(1)
1015 if( from_lat(from_lat_n) >= from_lat(1)) then ! increasing lat
1019 from_lats_mono_pos = .true.
1020 else ! decreasing lat
1024 from_lats_mono_pos = .false.
1027 !---------------------------------------------------------------------
1028 ! ... Set interpolation latitude indicies and del_lat
1029 !---------------------------------------------------------------------
1032 target_lat = xlat(i,j)
1034 if( target_lat <= min_lat ) then
1036 lat_interp(i,j) = latl
1037 else if( target_lat >= max_lat ) then
1039 if( from_lats_mono_pos ) then
1040 lat_interp(i,j) = latu - 1
1042 lat_interp(i,j) = latu + 1
1045 do m = latl,latu,lati
1046 if( target_lat < from_lat(m) ) then
1048 lat_interp(i,j) = min( from_lat_n,max( 1,n ) )
1050 (target_lat - from_lat(n))/(from_lat(m) - from_lat(n))
1058 end subroutine get_lat_interp_factors
1060 end module module_upper_bc_driver