43 integer,
public,
allocatable ::
bnd_iq(:)
70 private :: atmos_boundary_var_fillhalo
71 private :: atmos_boundary_alpha_fillhalo
72 private :: atmos_boundary_ref_fillhalo
73 private :: atmos_boundary_setalpha
74 private :: atmos_boundary_setinitval
75 private :: atmos_boundary_read
76 private :: atmos_boundary_write
77 private :: atmos_boundary_generate
78 private :: atmos_boundary_initialize_file
79 private :: atmos_boundary_initialize_online
80 private :: atmos_boundary_update_file
81 private :: atmos_boundary_update_online_parent
82 private :: atmos_boundary_update_online_daughter
83 private :: atmos_boundary_firstsend
84 private :: atmos_boundary_send
85 private :: atmos_boundary_recv
100 real(
rp),
intent(out) :: bnd_dens(:,:,:)
101 real(
rp),
intent(out) :: bnd_velz(:,:,:)
102 real(
rp),
intent(out) :: bnd_velx(:,:,:)
103 real(
rp),
intent(out) :: bnd_vely(:,:,:)
104 real(
rp),
intent(out) :: bnd_pott(:,:,:)
105 real(
rp),
intent(out) :: bnd_qtrc(:,:,:,:)
106 integer,
intent(in) :: now_step
107 integer,
intent(in) :: update_step
108 end subroutine getbnd
111 procedure(getbnd),
pointer :: get_boundary => null()
112 private :: get_boundary
113 private :: get_boundary_same_parent
114 private :: get_boundary_nearest_neighbor
115 private :: get_boundary_lerp_initpoint
116 private :: get_boundary_lerp_midpoint
123 character(len=H_SHORT),
private :: atmos_boundary_type =
'NONE'
124 character(len=H_LONG),
private :: atmos_boundary_in_basename =
''
125 logical,
private :: atmos_boundary_in_check_coordinates = .true.
126 logical,
private :: atmos_boundary_in_aggregate
127 character(len=H_LONG),
private :: atmos_boundary_out_basename =
''
128 character(len=H_MID),
private :: atmos_boundary_out_title =
'SCALE-RM BOUNDARY CONDITION'
129 character(len=H_SHORT),
private :: atmos_boundary_out_dtype =
'DEFAULT'
130 logical,
private :: atmos_boundary_out_aggregate
132 logical,
private :: atmos_boundary_use_dens = .false.
133 logical,
private :: atmos_boundary_use_velz = .false.
134 logical,
private :: atmos_boundary_use_velx = .false.
135 logical,
private :: atmos_boundary_use_vely = .false.
136 logical,
private :: atmos_boundary_use_pt = .false.
137 logical,
private :: atmos_boundary_use_qv = .false.
138 logical,
private :: atmos_boundary_use_qhyd = .false.
139 logical,
private :: atmos_boundary_use_chem = .false.
141 real(
rp),
private :: atmos_boundary_value_velz = 0.0_rp
142 real(
rp),
private :: atmos_boundary_value_velx = 0.0_rp
143 real(
rp),
private :: atmos_boundary_value_vely = 0.0_rp
144 real(
rp),
private :: atmos_boundary_value_pt = 300.0_rp
145 real(
rp),
private :: atmos_boundary_value_qtrc = 0.0_rp
147 real(
rp),
private :: atmos_boundary_alphafact_dens = 1.0_rp
148 real(
rp),
private :: atmos_boundary_alphafact_velz = 1.0_rp
149 real(
rp),
private :: atmos_boundary_alphafact_velx = 1.0_rp
150 real(
rp),
private :: atmos_boundary_alphafact_vely = 1.0_rp
151 real(
rp),
private :: atmos_boundary_alphafact_pt = 1.0_rp
152 real(
rp),
private :: atmos_boundary_alphafact_qtrc = 1.0_rp
154 real(
rp),
private :: atmos_boundary_fracz = 1.0_rp
155 real(
rp),
private :: atmos_boundary_fracx = 1.0_rp
156 real(
rp),
private :: atmos_boundary_fracy = 1.0_rp
157 real(
rp),
private :: atmos_boundary_tauz
158 real(
rp),
private :: atmos_boundary_taux
159 real(
rp),
private :: atmos_boundary_tauy
161 real(
dp),
private :: atmos_boundary_update_dt = 0.0_dp
162 integer,
private :: update_nstep
164 logical,
private :: atmos_grid_nudging_uv = .false.
165 logical,
private :: atmos_grid_nudging_pt = .false.
166 logical,
private :: atmos_grid_nudging_qv = .false.
167 real(
rp),
private :: atmos_grid_nudging_tau
169 real(
rp),
private,
allocatable :: atmos_boundary_ref_dens(:,:,:,:)
170 real(
rp),
private,
allocatable :: atmos_boundary_ref_velz(:,:,:,:)
171 real(
rp),
private,
allocatable :: atmos_boundary_ref_velx(:,:,:,:)
172 real(
rp),
private,
allocatable :: atmos_boundary_ref_vely(:,:,:,:)
173 real(
rp),
private,
allocatable :: atmos_boundary_ref_pott(:,:,:,:)
174 real(
rp),
private,
allocatable,
target :: atmos_boundary_ref_qtrc(:,:,:,:,:)
177 real(
rp),
private,
allocatable,
target :: q_work(:,:,:,:)
180 character(len=H_SHORT),
private :: atmos_boundary_interp_type =
'lerp_initpoint'
182 integer,
private :: atmos_boundary_start_date(6) = (/ -9999, 0, 0, 0, 0, 0 /)
184 integer,
private :: atmos_boundary_fid = -1
186 integer,
private :: now_step
187 integer,
private :: boundary_timestep = 0
188 logical,
private :: atmos_boundary_linear_v = .false.
189 logical,
private :: atmos_boundary_linear_h = .true.
190 real(
rp),
private :: atmos_boundary_exp_h = 2.0_rp
191 logical,
private :: atmos_boundary_online = .false.
192 logical,
private :: atmos_boundary_online_master = .false.
194 logical,
private :: atmos_boundary_dens_adjust = .false.
195 real(
rp),
private :: atmos_boundary_dens_adjust_tau = -1.0_rp
197 logical,
private :: do_parent_process = .false.
198 logical,
private :: do_daughter_process = .false.
199 logical,
private :: l_bnd = .false.
201 real(
dp),
private :: boundary_time_initdaysec
203 integer,
private :: ref_size = 3
204 integer,
private :: ref_old = 1
205 integer,
private :: ref_now = 2
206 integer,
private :: ref_new = 3
209 real(
dp),
private :: masstot_now = 0.0_dp
210 real(
dp),
private :: massflx_now = 0.0_dp
211 real(
rp),
allocatable,
private :: areazuy_w(:,:), areazuy_e(:,:)
212 real(
rp),
allocatable,
private :: offset_time_fact(:)
213 real(
rp),
allocatable,
private :: mflux_offset_x(:,:,:,:)
214 real(
rp),
allocatable,
private :: mflux_offset_y(:,:,:,:)
215 real(
rp),
allocatable,
private,
target :: zero_x(:,:), zero_y(:,:)
252 namelist / param_atmos_boundary / &
253 atmos_boundary_type, &
254 atmos_boundary_in_basename, &
255 atmos_boundary_in_check_coordinates, &
256 atmos_boundary_in_aggregate, &
257 atmos_boundary_out_basename, &
258 atmos_boundary_out_title, &
259 atmos_boundary_out_dtype, &
260 atmos_boundary_out_aggregate, &
261 atmos_boundary_use_velz, &
262 atmos_boundary_use_velx, &
263 atmos_boundary_use_vely, &
264 atmos_boundary_use_pt, &
265 atmos_boundary_use_dens, &
266 atmos_boundary_use_qv, &
267 atmos_boundary_use_qhyd, &
268 atmos_boundary_use_chem, &
269 atmos_boundary_dens_adjust, &
270 atmos_boundary_dens_adjust_tau, &
271 atmos_boundary_value_velz, &
272 atmos_boundary_value_velx, &
273 atmos_boundary_value_vely, &
274 atmos_boundary_value_pt, &
275 atmos_boundary_value_qtrc, &
276 atmos_boundary_alphafact_dens, &
277 atmos_boundary_alphafact_velz, &
278 atmos_boundary_alphafact_velx, &
279 atmos_boundary_alphafact_vely, &
280 atmos_boundary_alphafact_pt, &
281 atmos_boundary_alphafact_qtrc, &
283 atmos_boundary_fracz, &
284 atmos_boundary_fracx, &
285 atmos_boundary_fracy, &
286 atmos_boundary_tauz, &
287 atmos_boundary_taux, &
288 atmos_boundary_tauy, &
289 atmos_boundary_update_dt, &
290 atmos_boundary_start_date, &
291 atmos_boundary_linear_v, &
292 atmos_boundary_linear_h, &
293 atmos_boundary_exp_h, &
294 atmos_boundary_interp_type, &
295 atmos_grid_nudging_uv, &
296 atmos_grid_nudging_pt, &
297 atmos_grid_nudging_qv, &
298 atmos_grid_nudging_tau
300 integer ::
k, i, j, iq
305 log_info(
"ATMOS_BOUNDARY_setup",*)
'Setup'
308 atmos_boundary_tauz = dt * 10.0_rp
309 atmos_boundary_taux = dt * 10.0_rp
310 atmos_boundary_tauy = dt * 10.0_rp
315 atmos_grid_nudging_tau = 10.0_rp * 24.0_rp * 3600.0_rp
319 read(
io_fid_conf,nml=param_atmos_boundary,iostat=ierr)
321 log_info(
"ATMOS_BOUNDARY_setup",*)
'Not found namelist. Default used.'
322 elseif( ierr > 0 )
then
323 log_error(
"ATMOS_BOUNDARY_setup",*)
'Not appropriate names in namelist PARAM_ATMOS_BOUNDARY. Check!'
326 log_nml(param_atmos_boundary)
330 atmos_boundary_online = .false.
333 atmos_boundary_online = .false.
335 atmos_boundary_online = .true.
338 do_parent_process = .false.
339 do_daughter_process = .false.
340 atmos_boundary_online_master = .false.
341 if ( atmos_boundary_online )
then
343 do_parent_process = .true.
345 atmos_boundary_online_master = .true.
349 do_daughter_process = .true.
360 if( atmos_boundary_use_qhyd )
then
367 if( atmos_boundary_use_chem )
then
374 if ( atmos_boundary_dens_adjust_tau <= 0.0_rp )
then
375 atmos_boundary_dens_adjust_tau = max(
real(atmos_boundary_update_dt,kind=
rp) / 6.0_rp, &
376 atmos_boundary_taux, atmos_boundary_tauy )
412 if ( atmos_boundary_type ==
'REAL' .OR. do_daughter_process )
then
420 select case(atmos_boundary_interp_type)
422 get_boundary => get_boundary_same_parent
423 case(
'nearest_neighbor')
424 get_boundary => get_boundary_nearest_neighbor
425 case(
'lerp_initpoint')
426 get_boundary => get_boundary_lerp_initpoint
427 case(
'lerp_midpoint')
428 get_boundary => get_boundary_lerp_midpoint
430 log_error(
"ATMOS_BOUNDARY_setup",*)
'Wrong parameter in ATMOS_BOUNDARY_interp_TYPE. Check!'
434 allocate( atmos_boundary_ref_dens(
ka,
ia,
ja,ref_size) )
435 allocate( atmos_boundary_ref_velz(
ka,
ia,
ja,ref_size) )
436 allocate( atmos_boundary_ref_velx(
ka,
ia,
ja,ref_size) )
437 allocate( atmos_boundary_ref_vely(
ka,
ia,
ja,ref_size) )
438 allocate( atmos_boundary_ref_pott(
ka,
ia,
ja,ref_size) )
439 allocate( atmos_boundary_ref_qtrc(
ka,
ia,
ja,
bnd_qa,ref_size) )
440 atmos_boundary_ref_dens(:,:,:,:) = undef
441 atmos_boundary_ref_velz(:,:,:,:) = undef
442 atmos_boundary_ref_velx(:,:,:,:) = undef
443 atmos_boundary_ref_vely(:,:,:,:) = undef
444 atmos_boundary_ref_pott(:,:,:,:) = undef
445 atmos_boundary_ref_qtrc(:,:,:,:,:) = undef
448 if ( do_daughter_process )
then
449 call atmos_boundary_initialize_online
451 if ( atmos_boundary_in_basename /=
'' )
then
452 call atmos_boundary_initialize_file
454 log_error(
"ATMOS_BOUNDARY_setup",*)
'You need specify ATMOS_BOUNDARY_IN_BASENAME'
459 call atmos_boundary_setalpha
464 allocate( areazuy_w(
ka,
ja), areazuy_e(
ka,
ja) )
465 allocate( mflux_offset_x(
ka,
ja,2,2), mflux_offset_y(
ka,
ia,2,2) )
477 mflux_offset_x(
k,j,:,:) = 0.0_rp
483 mflux_offset_y(
k,i,:,:) = 0.0_rp
487 elseif ( atmos_boundary_type ==
'NONE' )
then
491 elseif ( atmos_boundary_type ==
'CONST' )
then
493 call atmos_boundary_setalpha
497 elseif ( atmos_boundary_type ==
'INIT' )
then
499 call atmos_boundary_setalpha
503 elseif ( atmos_boundary_type ==
'OFFLINE' )
then
505 if ( atmos_boundary_in_basename /=
'' )
then
506 call atmos_boundary_read
508 log_error(
"ATMOS_BOUNDARY_setup",*)
'You need specify ATMOS_BOUNDARY_IN_BASENAME'
515 log_error(
"ATMOS_BOUNDARY_setup",*)
'unsupported ATMOS_BOUNDARY_TYPE. Check!', trim(atmos_boundary_type)
524 log_info(
"ATMOS_BOUNDARY_setup",*)
'Atmospheric boundary parameters '
525 log_info_cont(*)
'Atmospheric boundary type : ', atmos_boundary_type
527 log_info_cont(*)
'Is VELZ used in atmospheric boundary? : ', atmos_boundary_use_velz
528 log_info_cont(*)
'Is VELX used in atmospheric boundary? : ', atmos_boundary_use_velx
529 log_info_cont(*)
'Is VELY used in atmospheric boundary? : ', atmos_boundary_use_vely
530 log_info_cont(*)
'Is PT used in atmospheric boundary? : ', atmos_boundary_use_pt
531 log_info_cont(*)
'Is DENS used in atmospheric boundary? : ', atmos_boundary_use_dens
532 log_info_cont(*)
'Is QV used in atmospheric boundary? : ', atmos_boundary_use_qv
533 log_info_cont(*)
'Is QHYD used in atmospheric boundary? : ', atmos_boundary_use_qhyd
534 log_info_cont(*)
'Is CHEM used in atmospheric boundary? : ', atmos_boundary_use_chem
536 log_info_cont(*)
'Atmospheric boundary VELZ values : ', atmos_boundary_value_velz
537 log_info_cont(*)
'Atmospheric boundary VELX values : ', atmos_boundary_value_velx
538 log_info_cont(*)
'Atmospheric boundary VELY values : ', atmos_boundary_value_vely
539 log_info_cont(*)
'Atmospheric boundary PT values : ', atmos_boundary_value_pt
540 log_info_cont(*)
'Atmospheric boundary QTRC values : ', atmos_boundary_value_qtrc
543 log_info_cont(*)
'Atmospheric boundary z-fraction : ', atmos_boundary_fracz
544 log_info_cont(*)
'Atmospheric boundary x-fraction : ', atmos_boundary_fracx
545 log_info_cont(*)
'Atmospheric boundary y-fraction : ', atmos_boundary_fracy
546 log_info_cont(*)
'Atmospheric boundary z-relaxation time : ', atmos_boundary_tauz
547 log_info_cont(*)
'Atmospheric boundary x-relaxation time : ', atmos_boundary_taux
548 log_info_cont(*)
'Atmospheric boundary y-relaxation time : ', atmos_boundary_tauy
550 log_info_cont(*)
'Atmospheric boundary update dt : ', atmos_boundary_update_dt
551 log_info_cont(*)
'Atmospheric boundary start date : ', atmos_boundary_start_date(:)
553 log_info_cont(*)
'Linear profile in vertically relax region : ', atmos_boundary_linear_v
554 log_info_cont(*)
'Linear profile in horizontally relax region : ', atmos_boundary_linear_h
555 log_info_cont(*)
'Non-linear factor in horizontally relax region : ', atmos_boundary_exp_h
557 log_info_cont(*)
'Online nesting for lateral boundary : ', atmos_boundary_online
559 log_info_cont(*)
'Does lateral boundary exist in this domain? : ', l_bnd
561 log_info_cont(*)
'Lateral boundary interporation type : ', trim(atmos_boundary_interp_type)
564 log_info_cont(*)
'Is grid nudging used for VELX & VELY? : ', atmos_grid_nudging_uv
565 log_info_cont(*)
'Is grid nudging used for POTT? : ', atmos_grid_nudging_pt
566 log_info_cont(*)
'Is grid nudging used for QV? : ', atmos_grid_nudging_qv
567 log_info_cont(*)
'Relaxation time for grid nudging : ', atmos_grid_nudging_tau
569 log_info_cont(*)
'Density adjustment : ', atmos_boundary_dens_adjust
570 if ( atmos_boundary_dens_adjust )
then
571 log_info_cont(*)
'Density relaxation time : ', atmos_boundary_dens_adjust_tau
575 allocate( q_work(
ka,
ia,
ja,nestqa) )
578 allocate( zero_x(
ka,
ja), zero_y(
ka,
ia) )
614 if ( do_parent_process )
then
615 call atmos_boundary_firstsend( &
616 dens,
momz,
momx,
momy,
rhot,
qtrc(:,:,:,
qs_mp:
qe_mp),
qv,
qe )
622 if ( do_daughter_process )
then
625 if ( atmos_boundary_in_basename /=
'' )
then
630 elseif ( atmos_boundary_type ==
'CONST' )
then
632 call atmos_boundary_generate
634 elseif ( atmos_boundary_type ==
'INIT' )
then
636 call atmos_boundary_setinitval(
dens, &
644 if( atmos_boundary_out_basename /=
'' )
then
645 call atmos_boundary_write
664 subroutine atmos_boundary_var_fillhalo
713 end subroutine atmos_boundary_var_fillhalo
717 subroutine atmos_boundary_alpha_fillhalo
766 end subroutine atmos_boundary_alpha_fillhalo
770 subroutine atmos_boundary_ref_fillhalo( &
778 integer,
intent(in) :: ref_idx
790 atmos_boundary_ref_dens( 1:
ks-1,i,j,ref_idx) = atmos_boundary_ref_dens(
ks,i,j,ref_idx)
791 atmos_boundary_ref_velz( 1:
ks-1,i,j,ref_idx) = atmos_boundary_ref_velz(
ks,i,j,ref_idx)
792 atmos_boundary_ref_velx( 1:
ks-1,i,j,ref_idx) = atmos_boundary_ref_velx(
ks,i,j,ref_idx)
793 atmos_boundary_ref_vely( 1:
ks-1,i,j,ref_idx) = atmos_boundary_ref_vely(
ks,i,j,ref_idx)
794 atmos_boundary_ref_pott( 1:
ks-1,i,j,ref_idx) = atmos_boundary_ref_pott(
ks,i,j,ref_idx)
796 atmos_boundary_ref_dens(
ke+1:
ka, i,j,ref_idx) = atmos_boundary_ref_dens(
ke,i,j,ref_idx)
797 atmos_boundary_ref_velz(
ke+1:
ka, i,j,ref_idx) = atmos_boundary_ref_velz(
ke,i,j,ref_idx)
798 atmos_boundary_ref_velx(
ke+1:
ka, i,j,ref_idx) = atmos_boundary_ref_velx(
ke,i,j,ref_idx)
799 atmos_boundary_ref_vely(
ke+1:
ka, i,j,ref_idx) = atmos_boundary_ref_vely(
ke,i,j,ref_idx)
800 atmos_boundary_ref_pott(
ke+1:
ka, i,j,ref_idx) = atmos_boundary_ref_pott(
ke,i,j,ref_idx)
803 atmos_boundary_ref_qtrc( 1:
ks-1,i,j,iq,ref_idx) = atmos_boundary_ref_qtrc(
ks,i,j,iq,ref_idx)
804 atmos_boundary_ref_qtrc(
ke+1:
ka, i,j,iq,ref_idx) = atmos_boundary_ref_qtrc(
ke,i,j,iq,ref_idx)
809 call comm_vars8( atmos_boundary_ref_dens(:,:,:,ref_idx), 1 )
810 call comm_vars8( atmos_boundary_ref_velz(:,:,:,ref_idx), 2 )
811 call comm_vars8( atmos_boundary_ref_velx(:,:,:,ref_idx), 3 )
812 call comm_vars8( atmos_boundary_ref_vely(:,:,:,ref_idx), 4 )
813 call comm_vars8( atmos_boundary_ref_pott(:,:,:,ref_idx), 5 )
816 call comm_vars8( atmos_boundary_ref_qtrc(:,:,:,iq,ref_idx), 5+iq )
819 call comm_wait ( atmos_boundary_ref_dens(:,:,:,ref_idx), 1, .false. )
820 call comm_wait ( atmos_boundary_ref_velz(:,:,:,ref_idx), 2, .false. )
821 call comm_wait ( atmos_boundary_ref_velx(:,:,:,ref_idx), 3, .false. )
822 call comm_wait ( atmos_boundary_ref_vely(:,:,:,ref_idx), 4, .false. )
823 call comm_wait ( atmos_boundary_ref_pott(:,:,:,ref_idx), 5, .false. )
826 call comm_wait ( atmos_boundary_ref_qtrc(:,:,:,iq,ref_idx), 5+iq, .false. )
830 end subroutine atmos_boundary_ref_fillhalo
834 subroutine atmos_boundary_setalpha
849 real(
rp) :: coef_z, alpha_z1, alpha_z2
850 real(
rp) :: coef_x, alpha_x1, alpha_x2
851 real(
rp) :: coef_y, alpha_y1, alpha_y2
852 real(
rp) :: alpha_zm, alpha_xm, alpha_ym
855 real(
rp) :: alpha_nug
857 integer :: i, j,
k, iq
861 atmos_boundary_fracz = max( min( atmos_boundary_fracz, 1.0_rp ), eps )
862 atmos_boundary_fracx = max( min( atmos_boundary_fracx, 1.0_rp ), eps )
863 atmos_boundary_fracy = max( min( atmos_boundary_fracy, 1.0_rp ), eps )
865 if ( atmos_boundary_tauz <= 0.0_rp )
then
868 coef_z = 1.0_rp / atmos_boundary_tauz
871 if ( atmos_boundary_taux <= 0.0_rp )
then
874 coef_x = 1.0_rp / atmos_boundary_taux
877 if ( atmos_boundary_tauy <= 0.0_rp )
then
880 coef_y = 1.0_rp / atmos_boundary_tauy
883 if ( atmos_grid_nudging_tau <= 0.0_rp )
then
886 alpha_nug = 1.0_rp / atmos_grid_nudging_tau
910 if ( ee1 <= 1.0_rp - atmos_boundary_fracz )
then
913 ee1 = ( ee1 - 1.0_rp + atmos_boundary_fracz ) / atmos_boundary_fracz
917 if ( ee2 <= 1.0_rp - atmos_boundary_fracz )
then
920 ee2 = ( ee2 - 1.0_rp + atmos_boundary_fracz ) / atmos_boundary_fracz
923 if ( .not. atmos_boundary_linear_v )
then
924 if ( ee1 > 0.0_rp .AND. ee1 <= 0.5_rp )
then
925 ee1 = 0.5_rp * ( 1.0_rp - cos( ee1*pi ) )
926 elseif( ee1 > 0.5_rp .AND. ee1 <= 1.0_rp )
then
927 ee1 = 0.5_rp * ( 1.0_rp + sin( (ee1-0.5_rp)*pi ) )
929 if ( ee2 > 0.0_rp .AND. ee2 <= 0.5_rp )
then
930 ee2 = 0.5_rp * ( 1.0_rp - cos( ee2*pi ) )
931 elseif( ee2 > 0.5_rp .AND. ee2 <= 1.0_rp )
then
932 ee2 = 0.5_rp * ( 1.0_rp + sin( (ee2-0.5_rp)*pi ) )
936 alpha_z1 = coef_z * ee1
937 alpha_z2 = coef_z * ee2
938 alpha_zm = ee1 / atmos_boundary_dens_adjust_tau
942 if ( ee1 <= 1.0_rp - atmos_boundary_fracx )
then
945 ee1 = ( ee1 - 1.0_rp + atmos_boundary_fracx ) / atmos_boundary_fracx
949 if ( ee2 <= 1.0_rp - atmos_boundary_fracx )
then
952 ee2 = ( ee2 - 1.0_rp + atmos_boundary_fracx ) / atmos_boundary_fracx
955 if ( .not. atmos_boundary_linear_h )
then
956 ee1 = ee1 * exp( -(1.0_rp-ee1) * atmos_boundary_exp_h )
957 ee2 = ee2 * exp( -(1.0_rp-ee2) * atmos_boundary_exp_h )
960 alpha_x1 = coef_x * ee1
961 alpha_x2 = coef_x * ee2
962 alpha_xm = ee1 / atmos_boundary_dens_adjust_tau
966 if ( ee1 <= 1.0_rp - atmos_boundary_fracy )
then
969 ee1 = ( ee1 - 1.0_rp + atmos_boundary_fracy ) / atmos_boundary_fracy
973 if ( ee2 <= 1.0_rp - atmos_boundary_fracy )
then
976 ee2 = ( ee2 - 1.0_rp + atmos_boundary_fracy ) / atmos_boundary_fracy
979 if ( .not. atmos_boundary_linear_h )
then
980 ee1 = ee1 * exp( -(1.0_rp-ee1) * atmos_boundary_exp_h )
981 ee2 = ee2 * exp( -(1.0_rp-ee2) * atmos_boundary_exp_h )
984 alpha_y1 = coef_y * ee1
985 alpha_y2 = coef_y * ee2
986 alpha_ym = ee1 / atmos_boundary_dens_adjust_tau
991 .or. ( .not. do_daughter_process .and. atmos_boundary_use_velz ) )
then
996 if ( atmos_boundary_dens_adjust )
then
1008 if ( atmos_boundary_use_dens )
then
1013 if ( atmos_boundary_use_velz )
then
1018 if ( atmos_boundary_use_velx )
then
1023 if ( atmos_boundary_use_vely )
then
1028 if ( atmos_boundary_use_pt )
then
1035 if ( atmos_boundary_use_qv )
then
1048 if ( atmos_grid_nudging_uv )
then
1052 if ( atmos_grid_nudging_pt )
then
1055 if ( atmos_grid_nudging_qv )
then
1064 call atmos_boundary_alpha_fillhalo
1067 end subroutine atmos_boundary_setalpha
1071 subroutine atmos_boundary_setinitval( &
1072 DENS, MOMZ, MOMX, MOMY, RHOT, QTRC )
1076 real(
rp),
intent(in) :: momz(
ka,
ia,
ja)
1077 real(
rp),
intent(in) :: momx(
ka,
ia,
ja)
1078 real(
rp),
intent(in) :: momy(
ka,
ia,
ja)
1079 real(
rp),
intent(in) :: rhot(
ka,
ia,
ja)
1082 integer :: i, j,
k, iq, iqb
1125 call atmos_boundary_var_fillhalo
1128 end subroutine atmos_boundary_setinitval
1132 subroutine atmos_boundary_read
1137 file_cartesc_check_coordinates, &
1138 file_cartesc_read, &
1146 call file_cartesc_open( atmos_boundary_in_basename, fid, aggregate=atmos_boundary_in_aggregate )
1148 if ( atmos_boundary_in_check_coordinates )
then
1149 call file_cartesc_check_coordinates( fid, atmos=.true. )
1152 if ( atmos_boundary_use_dens &
1153 .OR. atmos_boundary_use_velz &
1154 .OR. atmos_boundary_use_velx &
1155 .OR. atmos_boundary_use_vely &
1156 .OR. atmos_boundary_use_pt &
1160 if ( atmos_boundary_use_dens )
then
1164 if ( atmos_boundary_use_velz )
then
1169 if ( atmos_boundary_use_velx )
then
1174 if ( atmos_boundary_use_vely )
then
1179 if ( atmos_boundary_use_pt )
then
1195 call atmos_boundary_var_fillhalo
1196 call atmos_boundary_alpha_fillhalo
1199 end subroutine atmos_boundary_read
1203 subroutine atmos_boundary_write
1208 file_cartesc_write_var, &
1215 integer :: vid_dens, vid_a_dens
1216 integer :: vid_velz, vid_a_velz
1217 integer :: vid_velx, vid_a_velx
1218 integer :: vid_vely, vid_a_vely
1219 integer :: vid_pott, vid_a_pott
1225 atmos_boundary_out_dtype, &
1227 aggregate = atmos_boundary_out_aggregate )
1229 if ( atmos_boundary_use_dens &
1230 .OR. atmos_boundary_use_velz &
1231 .OR. atmos_boundary_use_velx &
1232 .OR. atmos_boundary_use_vely &
1233 .OR. atmos_boundary_use_pt &
1235 call file_cartesc_def_var( fid,
'DENS',
'Reference Density',
'kg/m3',
'ZXY', atmos_boundary_out_dtype, vid_dens )
1240 if ( atmos_boundary_use_dens .OR. l_bnd )
then
1241 call file_cartesc_def_var( fid,
'ALPHA_DENS',
'Alpha for DENS',
'1',
'ZXY', atmos_boundary_out_dtype, vid_a_dens )
1246 if ( atmos_boundary_use_velz .OR. (l_bnd .AND.
online_use_velz) )
then
1247 call file_cartesc_def_var( fid,
'VELZ',
'Reference Velocity w',
'm/s',
'ZHXY', atmos_boundary_out_dtype, vid_velz )
1248 call file_cartesc_def_var( fid,
'ALPHA_VELZ',
'Alpha for VELZ',
'1',
'ZHXY', atmos_boundary_out_dtype, vid_a_velz )
1253 if ( atmos_boundary_use_velx .OR. l_bnd )
then
1254 call file_cartesc_def_var( fid,
'VELX',
'Reference Velocity u',
'm/s',
'ZXHY', atmos_boundary_out_dtype, vid_velx )
1255 call file_cartesc_def_var( fid,
'ALPHA_VELX',
'Alpha for VELX',
'1',
'ZXHY', atmos_boundary_out_dtype, vid_a_velx )
1260 if ( atmos_boundary_use_vely .OR. l_bnd )
then
1261 call file_cartesc_def_var( fid,
'VELY',
'Reference Velocity y',
'm/s',
'ZXYH', atmos_boundary_out_dtype, vid_vely )
1262 call file_cartesc_def_var( fid,
'ALPHA_VELY',
'Alpha for VELY',
'1',
'ZXYH', atmos_boundary_out_dtype, vid_a_vely )
1267 if ( atmos_boundary_use_pt .OR. l_bnd )
then
1268 call file_cartesc_def_var( fid,
'PT',
'Reference PT',
'K',
'ZXY', atmos_boundary_out_dtype, vid_pott )
1269 call file_cartesc_def_var( fid,
'ALPHA_PT',
'Alpha for PT',
'1',
'ZXY', atmos_boundary_out_dtype, vid_a_pott )
1286 if ( vid_dens > 0 )
then
1290 if ( vid_a_dens > 0 )
then
1294 if ( vid_velz > 0 )
then
1299 if ( vid_velx > 0 )
then
1304 if ( vid_vely > 0 )
then
1309 if ( vid_pott > 0 )
then
1315 if ( vid_qtrc(iqb) > 0 )
then
1326 end subroutine atmos_boundary_write
1330 subroutine atmos_boundary_generate
1335 integer :: i, j,
k, iq
1354 call atmos_boundary_var_fillhalo
1357 end subroutine atmos_boundary_generate
1361 subroutine atmos_boundary_initialize_file
1370 file_cartesc_check_coordinates
1373 integer :: boundary_time_startday
1374 real(
dp) :: boundary_time_startsec
1375 real(
dp) :: boundary_time_startms
1376 integer :: boundary_time_offset_year
1377 character(len=27) :: boundary_chardate
1379 if ( atmos_boundary_start_date(1) == -9999 )
then
1384 boundary_time_startms = 0.0_dp
1385 boundary_time_offset_year = 0
1387 atmos_boundary_start_date(:), &
1388 boundary_time_startms )
1391 boundary_time_startsec, &
1392 atmos_boundary_start_date(:), &
1393 boundary_time_startms, &
1394 boundary_time_offset_year )
1398 log_info(
"ATMOS_BOUNDARY_initialize_file",
'(1x,A,A)')
'BOUNDARY START Date : ', boundary_chardate
1402 if ( atmos_boundary_in_check_coordinates )
then
1403 call file_cartesc_check_coordinates( atmos_boundary_fid, atmos=.true. )
1407 end subroutine atmos_boundary_initialize_file
1424 real(RP) :: bnd_DENS(KA,IA,JA)
1425 real(RP) :: bnd_VELZ(KA,IA,JA)
1426 real(RP) :: bnd_VELX(KA,IA,JA)
1427 real(RP) :: bnd_VELY(KA,IA,JA)
1428 real(RP) :: bnd_POTT(KA,IA,JA)
1429 real(RP) :: bnd_QTRC(KA,IA,JA,BND_QA)
1431 integer :: run_time_startdate(6)
1432 integer :: run_time_startday
1433 real(DP) :: run_time_startsec
1434 real(DP) :: run_time_startms
1435 integer :: run_time_offset_year
1436 real(DP) :: run_time_nowdaysec
1438 real(DP) :: boundary_diff_daysec
1439 real(RP) :: boundary_inc_offset
1440 integer :: fillgaps_steps
1444 integer :: i, j, k, n, iq
1447 if ( atmos_boundary_update_dt <= 0.0_dp )
then
1448 log_error(
"ATMOS_BOUNDARY_set_file",*)
'You need specify ATMOS_BOUNDARY_UPDATE_DT as larger than 0.0'
1451 update_nstep = nint( atmos_boundary_update_dt /
time_dtsec )
1452 if ( abs(update_nstep *
time_dtsec - atmos_boundary_update_dt) > 1e-10_dp )
then
1453 log_error(
"ATMOS_BOUNDARY_set_file",*)
'ATMOS_BOUNDARY_UPDATE_DT is not multiple of DT'
1459 run_time_startms = 0.0_dp
1460 run_time_offset_year = 0
1463 run_time_startsec, &
1464 run_time_startdate(:), &
1466 run_time_offset_year )
1470 boundary_diff_daysec = run_time_nowdaysec - boundary_time_initdaysec
1471 boundary_timestep = 1 + int( boundary_diff_daysec / atmos_boundary_update_dt )
1472 boundary_inc_offset = mod( boundary_diff_daysec, atmos_boundary_update_dt )
1473 fillgaps_steps = int( boundary_inc_offset /
time_dtsec )
1475 log_info(
"ATMOS_BOUNDARY_set_file",*)
'BOUNDARY TIMESTEP NUMBER FOR INIT:', boundary_timestep
1476 log_info(
"ATMOS_BOUNDARY_set_file",*)
'BOUNDARY OFFSET:', boundary_inc_offset
1477 log_info(
"ATMOS_BOUNDARY_set_file",*)
'BOUNDARY FILLGAPS STEPS:', fillgaps_steps
1480 if ( atmos_boundary_dens_adjust )
then
1481 allocate( offset_time_fact(0:update_nstep) )
1484 do n = 0, update_nstep
1485 offset_time_fact(n) = 1.0_rp - cos( 2.0_rp * pi * ( n - 1 ) / update_nstep )
1486 total = total + offset_time_fact(n)
1488 total = total / update_nstep
1490 do n = 0, update_nstep
1491 offset_time_fact(n) = offset_time_fact(n) / total
1496 call atmos_boundary_update_file( ref_now )
1498 if ( atmos_boundary_dens_adjust )
then
1502 boundary_timestep = boundary_timestep + 1
1503 call atmos_boundary_update_file( ref_new )
1505 if ( atmos_boundary_dens_adjust )
then
1517 atmos_boundary_ref_dens(k,i,j,ref_old) = atmos_boundary_ref_dens(k,i,j,ref_now)
1518 atmos_boundary_ref_velx(k,i,j,ref_old) = atmos_boundary_ref_velx(k,i,j,ref_now)
1519 atmos_boundary_ref_vely(k,i,j,ref_old) = atmos_boundary_ref_vely(k,i,j,ref_now)
1520 atmos_boundary_ref_pott(k,i,j,ref_old) = atmos_boundary_ref_pott(k,i,j,ref_now)
1522 atmos_boundary_ref_qtrc(k,i,j,iq,ref_old) = atmos_boundary_ref_qtrc(k,i,j,iq,ref_now)
1528 if ( atmos_boundary_use_velz )
then
1533 atmos_boundary_ref_velz(k,i,j,:) = atmos_boundary_value_velz
1539 now_step = fillgaps_steps
1549 subroutine atmos_boundary_initialize_online
1560 integer,
parameter :: handle = 2
1564 if ( nestqa >
bnd_qa )
then
1565 log_error(
"ATMOS_BOUNDARY_initialize_online",*)
'NEST_BND_QA exceeds BND_QA'
1566 log_error_cont(*)
'This must not be occur.'
1567 log_error_cont(*)
'Please send your configuration file to SCALE develop member.'
1574 end subroutine atmos_boundary_initialize_online
1592 integer,
parameter :: handle = 2
1597 integer :: i, j, k, n, iq
1601 boundary_timestep = 1
1602 log_info(
"ATMOS_BOUNDARY_set_online",*)
'BOUNDARY TIMESTEP NUMBER FOR INIT:', boundary_timestep
1604 call atmos_boundary_update_online_daughter( ref_now )
1606 if ( atmos_boundary_dens_adjust )
then
1610 boundary_timestep = boundary_timestep + 1
1611 log_info(
"ATMOS_BOUNDARY_set_online",*)
'BOUNDARY TIMESTEP NUMBER FOR INIT:', boundary_timestep
1613 call atmos_boundary_update_online_daughter( ref_new )
1615 if ( atmos_boundary_dens_adjust )
then
1625 atmos_boundary_ref_dens(k,i,j,ref_old) = atmos_boundary_ref_dens(k,i,j,ref_now)
1626 atmos_boundary_ref_velx(k,i,j,ref_old) = atmos_boundary_ref_velx(k,i,j,ref_now)
1627 atmos_boundary_ref_vely(k,i,j,ref_old) = atmos_boundary_ref_vely(k,i,j,ref_now)
1628 atmos_boundary_ref_pott(k,i,j,ref_old) = atmos_boundary_ref_pott(k,i,j,ref_now)
1630 atmos_boundary_ref_qtrc(k,i,j,iq,ref_old) = atmos_boundary_ref_qtrc(k,i,j,iq,ref_now)
1636 update_nstep = nint( atmos_boundary_update_dt /
time_dtsec )
1637 if ( update_nstep *
time_dtsec /= atmos_boundary_update_dt )
then
1638 log_error(
"ATMOS_BOUNDARY_set_online",*)
'DT of the parent is not multiple of the DT'
1642 log_error(
"ATMOS_BOUNDARY_set_online",*)
'DURATION must be the same as that of the parent'
1648 if ( atmos_boundary_dens_adjust )
then
1649 allocate( offset_time_fact(update_nstep) )
1652 do n = 0, update_nstep
1653 offset_time_fact(n) = 1.0_rp - cos( 2.0_rp * pi * ( n - 1 ) / update_nstep )
1654 total = total + offset_time_fact(n)
1656 total = total / update_nstep
1658 do n = 0, update_nstep
1659 offset_time_fact(n) = offset_time_fact(n) / total
1671 subroutine atmos_boundary_firstsend( &
1672 DENS, MOMZ, MOMX, MOMY, RHOT, QTRC, QV, Qe )
1680 real(RP),
intent(in) :: DENS(KA,IA,JA)
1681 real(RP),
intent(in) :: MOMZ(KA,IA,JA)
1682 real(RP),
intent(in) :: MOMX(KA,IA,JA)
1683 real(RP),
intent(in) :: MOMY(KA,IA,JA)
1684 real(RP),
intent(in) :: RHOT(KA,IA,JA)
1685 real(RP),
intent(in) :: QTRC(KA,IA,JA,QA_MP)
1686 real(RP),
intent(in) :: QV (KA,IA,JA)
1687 real(RP),
intent(in) :: Qe (KA,IA,JA,N_HYD)
1691 if ( do_parent_process )
then
1693 call atmos_boundary_send( dens, momz, momx, momy, rhot, qtrc, qv, qe )
1697 end subroutine atmos_boundary_firstsend
1714 if ( do_parent_process )
then
1719 if ( do_daughter_process )
then
1724 if ( atmos_boundary_fid > 0 )
then
1726 atmos_boundary_fid = -1
1743 logical,
intent(in) :: last_step
1751 now_step = now_step + 1
1754 if ( last_step )
then
1755 now_step = min( now_step, update_nstep-1 )
1756 else if ( now_step >= update_nstep )
then
1758 boundary_timestep = boundary_timestep + 1
1762 if ( do_daughter_process )
then
1763 call atmos_boundary_update_online_daughter( ref_new )
1765 call atmos_boundary_update_file( ref_new )
1768 if ( atmos_boundary_dens_adjust )
then
1776 if ( atmos_boundary_dens_adjust )
then
1780 elseif ( do_parent_process )
then
1783 log_error(
"ATMOS_BOUNDARY_update",*)
'[BUG] invalid path'
1795 if ( do_daughter_process )
then
1825 if ( do_parent_process )
then
1827 call atmos_boundary_update_online_parent(
dens,
momz,
momx,
momy,
rhot,
qtrc(:,:,:,
qs_mp:
qe_mp),
qv,
qe )
1839 subroutine atmos_boundary_update_file( ref )
1841 file_cartesc_read, &
1847 integer,
intent(in) :: ref
1849 integer :: fid, iq, iqb
1852 log_info(
"ATMOS_BOUNDARY_update_file",*)
"Atmos Boundary: read from boundary file(timestep=", boundary_timestep,
")"
1854 fid = atmos_boundary_fid
1856 call file_cartesc_read( fid,
'DENS',
'ZXY', atmos_boundary_ref_dens(:,:,:,ref), step=boundary_timestep )
1857 call file_cartesc_read( fid,
'VELX',
'ZXHY', atmos_boundary_ref_velx(:,:,:,ref), step=boundary_timestep )
1858 call file_cartesc_read( fid,
'VELY',
'ZXYH', atmos_boundary_ref_vely(:,:,:,ref), step=boundary_timestep )
1859 call file_cartesc_read( fid,
'PT',
'ZXY', atmos_boundary_ref_pott(:,:,:,ref), step=boundary_timestep )
1863 call file_cartesc_read( fid,
tracer_name(iq),
'ZXY', atmos_boundary_ref_qtrc(:,:,:,iqb,ref), step=boundary_timestep )
1870 call atmos_boundary_ref_fillhalo( ref )
1873 end subroutine atmos_boundary_update_file
1877 subroutine atmos_boundary_update_online_parent( &
1897 real(
rp),
intent(in) :: momz(
ka,
ia,
ja)
1898 real(
rp),
intent(in) :: momx(
ka,
ia,
ja)
1899 real(
rp),
intent(in) :: momy(
ka,
ia,
ja)
1900 real(
rp),
intent(in) :: rhot(
ka,
ia,
ja)
1902 real(
rp),
intent(in) :: qv (
ka,
ia,
ja)
1905 integer,
parameter :: handle = 1
1908 log_info(
"ATMOS_BOUNDARY_update_online_parent",*)
"ATMOS BOUNDARY update online: PARENT"
1914 call atmos_boundary_send(
dens, momz, momx, momy, rhot,
qtrc, qv, qe )
1917 end subroutine atmos_boundary_update_online_parent
1921 subroutine atmos_boundary_update_online_daughter( &
1929 integer,
intent(in) :: ref
1931 integer,
parameter :: handle = 2
1934 log_info(
"ATMOS_BOUNDARY_update_online_daughter",
'(1X,A,I5)')
'ATMOS BOUNDARY update online: DAUGHTER', boundary_timestep
1937 call atmos_boundary_recv( ref )
1940 call atmos_boundary_ref_fillhalo( ref )
1946 end subroutine atmos_boundary_update_online_daughter
1950 subroutine atmos_boundary_send( &
1951 DENS, MOMZ, MOMX, MOMY, RHOT, QTRC, QV, Qe )
1966 integer,
parameter :: handle = 1
1970 real(
rp),
intent(in) :: momz(
ka,
ia,
ja)
1971 real(
rp),
intent(in) :: momx(
ka,
ia,
ja)
1972 real(
rp),
intent(in) :: momy(
ka,
ia,
ja)
1973 real(
rp),
intent(in) :: rhot(
ka,
ia,
ja)
1975 real(
rp),
intent(in) :: qv (
ka,
ia,
ja)
1979 real(
rp),
pointer :: q(:,:,:,:)
1987 q(:,:,:,1) = qv(:,:,:)
1989 q(:,:,:,iq) = qe(:,:,:,iq-1)
2011 end subroutine atmos_boundary_send
2015 subroutine atmos_boundary_recv( &
2031 integer,
parameter :: handle = 2
2034 integer,
intent(in) :: ref_idx
2037 real(
rp),
pointer :: q(:,:,:,:)
2042 dummy_p(:,:,:,:) = 0.0_rp
2047 q => atmos_boundary_ref_qtrc(:,:,:,1:nestqa,ref_idx)
2057 dummy_p(:,:,:,1:nestqa), &
2058 atmos_boundary_ref_dens(:,:,:,ref_idx), &
2059 atmos_boundary_ref_velz(:,:,:,ref_idx), &
2060 atmos_boundary_ref_velx(:,:,:,ref_idx), &
2061 atmos_boundary_ref_vely(:,:,:,ref_idx), &
2062 atmos_boundary_ref_pott(:,:,:,ref_idx), &
2068 q(:,:,:,1), q(:,:,:,2:), &
2069 atmos_boundary_ref_qtrc(:,:,:,:,ref_idx) )
2073 end subroutine atmos_boundary_recv
2090 logical,
intent(in) :: use_velz
2092 real(RP) :: bnd_DENS(KA,IA,JA)
2093 real(RP) :: bnd_VELZ(KA,IA,JA)
2094 real(RP) :: bnd_VELX(KA,IA,JA)
2095 real(RP) :: bnd_VELY(KA,IA,JA)
2096 real(RP) :: bnd_POTT(KA,IA,JA)
2097 real(RP) :: bnd_QTRC(KA,IA,JA,BND_QA)
2099 integer :: i, j, k, iq, iqb
2103 call get_boundary( bnd_dens(:,:,:), &
2108 bnd_qtrc(:,:,:,:), &
2127 if ( use_velz )
then
2179 if ( use_velz )
then
2256 if ( use_velz )
then
2312 if ( use_velz )
then
2377 if ( use_velz )
then
2401 subroutine get_boundary_same_parent( &
2413 real(RP),
intent(out) :: bnd_DENS(:,:,:)
2414 real(RP),
intent(out) :: bnd_VELZ(:,:,:)
2415 real(RP),
intent(out) :: bnd_VELX(:,:,:)
2416 real(RP),
intent(out) :: bnd_VELY(:,:,:)
2417 real(RP),
intent(out) :: bnd_POTT(:,:,:)
2418 real(RP),
intent(out) :: bnd_QTRC(:,:,:,:)
2419 integer,
intent(in) :: now_step
2420 integer,
intent(in) :: update_step
2423 integer :: i, j, k, iq
2427 if ( now_step == update_step )
then
2437 bnd_dens(k,i,j) = atmos_boundary_ref_dens(k,i,j,ref)
2438 bnd_velz(k,i,j) = atmos_boundary_ref_velz(k,i,j,ref)
2439 bnd_velx(k,i,j) = atmos_boundary_ref_velx(k,i,j,ref)
2440 bnd_vely(k,i,j) = atmos_boundary_ref_vely(k,i,j,ref)
2441 bnd_pott(k,i,j) = atmos_boundary_ref_pott(k,i,j,ref)
2443 bnd_qtrc(k,i,j,iq) = atmos_boundary_ref_qtrc(k,i,j,iq,ref)
2450 end subroutine get_boundary_same_parent
2454 subroutine get_boundary_nearest_neighbor( &
2466 real(RP) :: EPS = 1.0e-4_rp
2469 real(RP),
intent(out) :: bnd_DENS(:,:,:)
2470 real(RP),
intent(out) :: bnd_VELZ(:,:,:)
2471 real(RP),
intent(out) :: bnd_VELX(:,:,:)
2472 real(RP),
intent(out) :: bnd_VELY(:,:,:)
2473 real(RP),
intent(out) :: bnd_POTT(:,:,:)
2474 real(RP),
intent(out) :: bnd_QTRC(:,:,:,:)
2475 integer,
intent(in) :: now_step
2476 integer,
intent(in) :: update_step
2479 integer :: i, j, k, iq
2482 real(RP) :: real_nstep
2483 real(RP) :: half_nstep
2486 real_nstep =
real( now_step, kind=rp )
2487 half_nstep =
real( update_nstep, kind=rp ) * 0.5_rp
2490 if( ( real_nstep - eps ) < half_nstep )
then
2494 else if( ( real_nstep - 1.0_rp + eps ) > half_nstep )
then
2507 bnd_dens(k,i,j) = atmos_boundary_ref_dens(k,i,j,ref_idx)
2508 bnd_velz(k,i,j) = atmos_boundary_ref_velz(k,i,j,ref_idx)
2509 bnd_velx(k,i,j) = atmos_boundary_ref_velx(k,i,j,ref_idx)
2510 bnd_vely(k,i,j) = atmos_boundary_ref_vely(k,i,j,ref_idx)
2511 bnd_pott(k,i,j) = atmos_boundary_ref_pott(k,i,j,ref_idx)
2513 bnd_qtrc(k,i,j,iq) = atmos_boundary_ref_qtrc(k,i,j,iq,ref_idx)
2520 end subroutine get_boundary_nearest_neighbor
2524 subroutine get_boundary_lerp_initpoint( &
2536 real(RP),
intent(out) :: bnd_DENS(:,:,:)
2537 real(RP),
intent(out) :: bnd_VELZ(:,:,:)
2538 real(RP),
intent(out) :: bnd_VELX(:,:,:)
2539 real(RP),
intent(out) :: bnd_VELY(:,:,:)
2540 real(RP),
intent(out) :: bnd_POTT(:,:,:)
2541 real(RP),
intent(out) :: bnd_QTRC(:,:,:,:)
2542 integer,
intent(in) :: now_step
2543 integer,
intent(in) :: update_step
2546 integer :: i, j, k, iq
2551 fact = ( now_step + 0.5_rp ) / update_step
2560 bnd_dens(k,i,j) = atmos_boundary_ref_dens(k,i,j,ref_now) * ( 1.0_rp-fact ) &
2561 + atmos_boundary_ref_dens(k,i,j,ref_new) * fact
2562 bnd_velz(k,i,j) = atmos_boundary_ref_velz(k,i,j,ref_now) * ( 1.0_rp-fact ) &
2563 + atmos_boundary_ref_velz(k,i,j,ref_new) * fact
2564 bnd_velx(k,i,j) = atmos_boundary_ref_velx(k,i,j,ref_now) * ( 1.0_rp-fact) &
2565 + atmos_boundary_ref_velx(k,i,j,ref_new) * fact
2566 bnd_vely(k,i,j) = atmos_boundary_ref_vely(k,i,j,ref_now) * ( 1.0_rp-fact) &
2567 + atmos_boundary_ref_vely(k,i,j,ref_new) * fact
2568 bnd_pott(k,i,j) = atmos_boundary_ref_pott(k,i,j,ref_now) * ( 1.0_rp-fact ) &
2569 + atmos_boundary_ref_pott(k,i,j,ref_new) * fact
2571 bnd_qtrc(k,i,j,iq) = atmos_boundary_ref_qtrc(k,i,j,iq,ref_now) * ( 1.0_rp-fact ) &
2572 + atmos_boundary_ref_qtrc(k,i,j,iq,ref_new) * fact
2579 end subroutine get_boundary_lerp_initpoint
2583 subroutine get_boundary_lerp_midpoint( &
2597 real(RP) :: EPS = 1.0e-4_rp
2600 real(RP),
intent(out) :: bnd_DENS(:,:,:)
2601 real(RP),
intent(out) :: bnd_VELZ(:,:,:)
2602 real(RP),
intent(out) :: bnd_VELX(:,:,:)
2603 real(RP),
intent(out) :: bnd_VELY(:,:,:)
2604 real(RP),
intent(out) :: bnd_POTT(:,:,:)
2605 real(RP),
intent(out) :: bnd_QTRC(:,:,:,:)
2606 integer,
intent(in) :: now_step
2607 integer,
intent(in) :: update_step
2610 integer :: i, j, k, iq
2612 real(RP) :: real_nstep
2613 real(RP) :: half_nstep
2617 real_nstep =
real( now_step, kind=rp )
2618 half_nstep =
real( update_nstep, kind=rp ) * 0.5_rp
2621 if( ( real_nstep - eps ) < half_nstep )
then
2623 t1 =
time_dtsec / atmos_boundary_update_dt * ( real_nstep + half_nstep - 0.5_rp )
2629 bnd_dens(k,i,j) = atmos_boundary_ref_dens(k,i,j,ref_now) * t1 &
2630 - atmos_boundary_ref_dens(k,i,j,ref_old) * ( t1 - 1.0_rp )
2631 bnd_velz(k,i,j) = atmos_boundary_ref_velz(k,i,j,ref_now) * t1 &
2632 - atmos_boundary_ref_velz(k,i,j,ref_old) * ( t1 - 1.0_rp )
2633 bnd_velx(k,i,j) = atmos_boundary_ref_velx(k,i,j,ref_now) * t1 &
2634 - atmos_boundary_ref_velx(k,i,j,ref_old) * ( t1 - 1.0_rp )
2635 bnd_vely(k,i,j) = atmos_boundary_ref_vely(k,i,j,ref_now) * t1 &
2636 - atmos_boundary_ref_vely(k,i,j,ref_old) * ( t1 - 1.0_rp )
2637 bnd_pott(k,i,j) = atmos_boundary_ref_pott(k,i,j,ref_now) * t1 &
2638 - atmos_boundary_ref_pott(k,i,j,ref_old) * ( t1 - 1.0_rp )
2640 bnd_qtrc(k,i,j,iq) = atmos_boundary_ref_qtrc(k,i,j,iq,ref_now) * t1 &
2641 - atmos_boundary_ref_qtrc(k,i,j,iq,ref_old) * ( t1 - 1.0_rp )
2648 else if( ( real_nstep - 1.0_rp + eps ) > half_nstep )
then
2650 t1 =
time_dtsec / atmos_boundary_update_dt * ( real_nstep - half_nstep - 0.5_rp )
2656 bnd_dens(k,i,j) = atmos_boundary_ref_dens(k,i,j,ref_new) * t1 &
2657 - atmos_boundary_ref_dens(k,i,j,ref_now) * ( t1 - 1.0_rp )
2658 bnd_velz(k,i,j) = atmos_boundary_ref_velz(k,i,j,ref_new) * t1 &
2659 - atmos_boundary_ref_velz(k,i,j,ref_now) * ( t1 - 1.0_rp )
2660 bnd_velx(k,i,j) = atmos_boundary_ref_velx(k,i,j,ref_new) * t1 &
2661 - atmos_boundary_ref_velx(k,i,j,ref_now) * ( t1 - 1.0_rp )
2662 bnd_vely(k,i,j) = atmos_boundary_ref_vely(k,i,j,ref_new) * t1 &
2663 - atmos_boundary_ref_vely(k,i,j,ref_now) * ( t1 - 1.0_rp )
2664 bnd_pott(k,i,j) = atmos_boundary_ref_pott(k,i,j,ref_new) * t1 &
2665 - atmos_boundary_ref_pott(k,i,j,ref_now) * ( t1 - 1.0_rp )
2667 bnd_qtrc(k,i,j,iq) = atmos_boundary_ref_qtrc(k,i,j,iq,ref_new) * t1 &
2668 - atmos_boundary_ref_qtrc(k,i,j,iq,ref_now) * ( t1 - 1.0_rp )
2677 t1 =
time_dtsec / atmos_boundary_update_dt * ( real_nstep + half_nstep - 1.0_rp )
2678 t2 =
time_dtsec / atmos_boundary_update_dt * ( real_nstep - half_nstep )
2684 bnd_dens(k,i,j) = atmos_boundary_ref_dens(k,i,j,ref_new) * t2 * 0.25_rp &
2685 + atmos_boundary_ref_dens(k,i,j,ref_now) * ( t1 - t2 + 3.0_rp ) * 0.25_rp &
2686 - atmos_boundary_ref_dens(k,i,j,ref_old) * ( t1 - 1.0_rp ) * 0.25_rp
2687 bnd_velz(k,i,j) = atmos_boundary_ref_velz(k,i,j,ref_new) * t2 * 0.25_rp &
2688 + atmos_boundary_ref_velz(k,i,j,ref_now) * ( t1 - t2 + 3.0_rp ) * 0.25_rp &
2689 - atmos_boundary_ref_velz(k,i,j,ref_old) * ( t1 - 1.0_rp ) * 0.25_rp
2690 bnd_velx(k,i,j) = atmos_boundary_ref_velx(k,i,j,ref_new) * t2 * 0.25_rp &
2691 + atmos_boundary_ref_velx(k,i,j,ref_now) * ( t1 - t2 + 3.0_rp ) * 0.25_rp &
2692 - atmos_boundary_ref_velx(k,i,j,ref_old) * ( t1 - 1.0_rp ) * 0.25_rp
2693 bnd_vely(k,i,j) = atmos_boundary_ref_vely(k,i,j,ref_new) * t2 * 0.25_rp &
2694 + atmos_boundary_ref_vely(k,i,j,ref_now) * ( t1 - t2 + 3.0_rp ) * 0.25_rp &
2695 - atmos_boundary_ref_vely(k,i,j,ref_old) * ( t1 - 1.0_rp ) * 0.25_rp
2696 bnd_pott(k,i,j) = atmos_boundary_ref_pott(k,i,j,ref_new) * t2 * 0.25_rp &
2697 + atmos_boundary_ref_pott(k,i,j,ref_now) * ( t1 - t2 + 3.0_rp ) * 0.25_rp &
2698 - atmos_boundary_ref_pott(k,i,j,ref_old) * ( t1 - 1.0_rp ) * 0.25_rp
2700 bnd_qtrc(k,i,j,iq) = atmos_boundary_ref_qtrc(k,i,j,iq,ref_new) * t2 * 0.25_rp &
2701 + atmos_boundary_ref_qtrc(k,i,j,iq,ref_now) * ( t1 - t2 + 3.0_rp ) * 0.25_rp &
2702 - atmos_boundary_ref_qtrc(k,i,j,iq,ref_old) * ( t1 - 1.0_rp )
2711 end subroutine get_boundary_lerp_midpoint
2730 subroutine history_bnd( &
2731 ATMOS_BOUNDARY_DENS, &
2732 ATMOS_BOUNDARY_VELZ, &
2733 ATMOS_BOUNDARY_VELX, &
2734 ATMOS_BOUNDARY_VELY, &
2735 ATMOS_BOUNDARY_POTT, &
2736 ATMOS_BOUNDARY_QTRC )
2742 real(RP),
intent(in) :: ATMOS_BOUNDARY_DENS(KA,IA,JA)
2743 real(RP),
intent(in) :: ATMOS_BOUNDARY_VELZ(KA,IA,JA)
2744 real(RP),
intent(in) :: ATMOS_BOUNDARY_VELX(KA,IA,JA)
2745 real(RP),
intent(in) :: ATMOS_BOUNDARY_VELY(KA,IA,JA)
2746 real(RP),
intent(in) :: ATMOS_BOUNDARY_POTT(KA,IA,JA)
2747 real(RP),
intent(in) :: ATMOS_BOUNDARY_QTRC(KA,IA,JA,BND_QA)
2751 call file_history_in( atmos_boundary_dens(:,:,:),
'DENS_BND',
'Boundary Density',
'kg/m3' )
2752 call file_history_in( atmos_boundary_velz(:,:,:),
'VELZ_BND',
'Boundary velocity z-direction',
'm/s', dim_type=
'ZHXY' )
2753 call file_history_in( atmos_boundary_velx(:,:,:),
'VELX_BND',
'Boundary velocity x-direction',
'm/s', dim_type=
'ZXHY' )
2754 call file_history_in( atmos_boundary_vely(:,:,:),
'VELY_BND',
'Boundary velocity y-direction',
'm/s', dim_type=
'ZXYH' )
2755 call file_history_in( atmos_boundary_pott(:,:,:),
'PT_BND',
'Boundary potential temperature',
'K' )
2759 call file_history_in( atmos_boundary_qtrc(:,:,:,iqb), trim(
tracer_name(iq))//
'_BND', &
2765 end subroutine history_bnd
2786 integer,
intent(in) :: ref
2788 real(DP) :: masstot, masstot_current
2790 real(DP) :: offset_band, offset_bias
2792 real(DP) :: flx_w, flx_e, flx_s, flx_n
2793 real(DP) :: ref_w, ref_e, ref_s, ref_n
2795 real(RP),
target :: work_x(KA,JA), work_y(KA,IA)
2796 real(RP),
pointer :: ptr(:,:)
2801 call statistics_total( ka,
ks,
ke, ia,
is,
ie, ja,
js,
je, &
2802 atmos_boundary_ref_dens(:,:,:,ref), &
2804 vol(:,:,:), totvol, &
2805 log_suppress = .true., global = .true., &
2820 work_x(k,j) = atmos_boundary_ref_velx(k,
is-1,j,ref) &
2821 * ( atmos_boundary_ref_dens(k,
is-1,j,ref) + atmos_boundary_ref_dens(k,
is,j,ref) ) * 0.5_rp
2828 call statistics_total( ka,
ks,
ke, ja,
js,
je, &
2829 ptr(:,:),
"MFLUX_bnd_w", &
2830 areazuy_w(:,:), totareazuy_x(
is-1), &
2831 log_suppress = .true., global = .true., &
2837 work_x(k,j) = dens_ref(k,
is,j)
2841 call statistics_total( ka,
ks,
ke, ja,
js,
je, &
2842 ptr(:,:),
"DENS_ref_w", &
2843 areazuy_w(:,:), totareazuy_x(
is-1), &
2844 log_suppress = .true., global = .true., &
2852 work_x(k,j) = atmos_boundary_ref_velx(k,
ie,j,ref) &
2853 * ( atmos_boundary_ref_dens(k,
ie,j,ref) + atmos_boundary_ref_dens(k,
ie+1,j,ref) ) * 0.5_rp
2860 call statistics_total( ka,
ks,
ke, ja,
js,
je, &
2861 ptr(:,:),
"MFLUX_bnd_e", &
2862 areazuy_e(:,:), totareazuy_x(
ie), &
2863 log_suppress = .true., global = .true., &
2869 work_x(k,j) = dens_ref(k,
ie,j)
2873 call statistics_total( ka,
ks,
ke, ja,
js,
je, &
2874 ptr(:,:),
"DENS_ref_e", &
2875 areazuy_e(:,:), totareazuy_x(
ie), &
2876 log_suppress = .true., global = .true., &
2884 work_y(k,i) = atmos_boundary_ref_vely(k,i,
js-1,ref) &
2885 * ( atmos_boundary_ref_dens(k,i,
js-1,ref) + atmos_boundary_ref_dens(k,i,
js,ref) ) * 0.5_rp
2892 call statistics_total( ka,
ks,
ke, ia,
is,
ie, &
2893 ptr(:,:),
"MFLUX_bnd_s", &
2894 areazxv_y(:,:,
js-1), totareazxv_y(
js-1), &
2895 log_suppress = .true., global = .true., &
2901 work_y(k,i) = dens_ref(k,i,
js)
2905 call statistics_total( ka,
ks,
ke, ia,
is,
ie, &
2906 ptr(:,:),
"DENS_ref_s", &
2907 areazxv_y(:,:,
js-1), totareazxv_y(
js-1), &
2908 log_suppress = .true., global = .true., &
2916 work_y(k,i) = atmos_boundary_ref_vely(k,i,
je,ref) &
2917 * ( atmos_boundary_ref_dens(k,i,
je,ref) + atmos_boundary_ref_dens(k,i,
je+1,ref) ) * 0.5_rp
2924 call statistics_total( ka,
ks,
ke, ia,
is,
ie, &
2925 ptr(:,:),
"MFLX_bnd_n", &
2926 areazxv_y(:,:,
je), totareazxv_y(
je), &
2927 log_suppress = .true., global = .true., &
2933 work_y(k,i) = dens_ref(k,i,
je)
2937 call statistics_total( ka,
ks,
ke, ia,
is,
ie, &
2938 ptr(:,:),
"DENS_ref_n", &
2939 areazxv_y(:,:,
je), totareazxv_y(
je), &
2940 log_suppress = .true., global = .true., &
2943 massflx = flx_w - flx_e + flx_s - flx_n
2945 offset_band = ( masstot - masstot_now ) / atmos_boundary_update_dt &
2946 - ( massflx + massflx_now ) * 0.5_dp
2949 log_info(
"ATMOS_BOUNDARY_calc_mass",*)
"Offset_band is: ", offset_band,
"(", masstot, masstot_now, massflx, massflx_now,
")"
2951 ref_tot = ref_w + ref_e + ref_s + ref_n
2952 offset_band = offset_band / ref_tot
2955 log_info_cont(*)
" per dens ", offset_band
2962 mflux_offset_x(k,j,1,1) = offset_band * dens_ref(k,
is,j)
2971 mflux_offset_x(k,j,2,1) = - offset_band * dens_ref(k,
ie,j)
2980 mflux_offset_y(k,i,1,1) = offset_band * dens_ref(k,i,
js)
2989 mflux_offset_y(k,i,2,1) = - offset_band * dens_ref(k,i,
je)
2995 masstot_now = masstot
2996 massflx_now = massflx
3003 integer :: k, i, j, n