43 integer,
public,
allocatable ::
bnd_iq(:)
70 private :: atmos_boundary_var_fillhalo
71 private :: atmos_boundary_alpha_fillhalo
72 private :: atmos_boundary_setalpha
73 private :: atmos_boundary_setinitval
74 private :: atmos_boundary_read
75 private :: atmos_boundary_write
76 private :: atmos_boundary_generate
77 private :: atmos_boundary_initialize_file
78 private :: atmos_boundary_initialize_online
79 private :: atmos_boundary_update
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
92 character(len=H_SHORT),
private :: atmos_boundary_type =
'NONE'
93 character(len=H_LONG),
private :: atmos_boundary_in_basename =
''
94 logical,
private :: atmos_boundary_in_basename_add_num = .false.
95 integer,
private :: atmos_boundary_in_number_of_files = 1
96 logical,
private :: atmos_boundary_in_check_coordinates = .true.
97 integer,
private :: atmos_boundary_in_step_limit = 1000
98 logical,
private :: atmos_boundary_in_aggregate
99 character(len=H_LONG),
private :: atmos_boundary_out_basename =
''
100 character(len=H_MID),
private :: atmos_boundary_out_title =
'SCALE-RM BOUNDARY CONDITION'
101 character(len=H_SHORT),
private :: atmos_boundary_out_dtype =
'DEFAULT'
102 logical,
private :: atmos_boundary_out_aggregate
104 logical,
private :: atmos_boundary_use_dens = .false.
105 logical,
private :: atmos_boundary_use_velz = .false.
106 logical,
private :: atmos_boundary_use_velx = .false.
107 logical,
private :: atmos_boundary_use_vely = .false.
108 logical,
private :: atmos_boundary_use_pt = .false.
109 logical,
private :: atmos_boundary_use_qv = .false.
110 logical,
private :: atmos_boundary_use_qhyd = .false.
111 logical,
private :: atmos_boundary_use_chem = .false.
113 real(
rp),
private :: atmos_boundary_value_velz = 0.0_rp
114 real(
rp),
private :: atmos_boundary_value_velx = 0.0_rp
115 real(
rp),
private :: atmos_boundary_value_vely = 0.0_rp
116 real(
rp),
private :: atmos_boundary_value_pt = 300.0_rp
117 real(
rp),
private :: atmos_boundary_value_qtrc = 0.0_rp
119 real(
rp),
private :: atmos_boundary_alphafact_dens = 1.0_rp
120 real(
rp),
private :: atmos_boundary_alphafact_velz = 1.0_rp
121 real(
rp),
private :: atmos_boundary_alphafact_velx = 1.0_rp
122 real(
rp),
private :: atmos_boundary_alphafact_vely = 1.0_rp
123 real(
rp),
private :: atmos_boundary_alphafact_pt = 1.0_rp
124 real(
rp),
private :: atmos_boundary_alphafact_qtrc = 1.0_rp
126 real(
rp),
private :: atmos_boundary_fracz = 1.0_rp
127 real(
rp),
private :: atmos_boundary_fracx = 1.0_rp
128 real(
rp),
private :: atmos_boundary_fracy = 1.0_rp
129 real(
rp),
private :: atmos_boundary_tauz
130 real(
rp),
private :: atmos_boundary_taux
131 real(
rp),
private :: atmos_boundary_tauy
133 real(
dp),
private :: update_dt = 0.0_dp
134 integer,
private :: update_nstep
136 logical,
private :: atmos_grid_nudging_uv = .false.
137 logical,
private :: atmos_grid_nudging_pt = .false.
138 logical,
private :: atmos_grid_nudging_qv = .false.
139 real(
rp),
private :: atmos_grid_nudging_tau
142 real(
rp),
private,
allocatable :: dens_ref(:,:,:)
143 real(
rp),
private,
allocatable :: velz_ref(:,:,:)
144 real(
rp),
private,
allocatable :: velx_ref(:,:,:)
145 real(
rp),
private,
allocatable :: vely_ref(:,:,:)
146 real(
rp),
private,
allocatable :: pott_ref(:,:,:)
147 real(
rp),
private,
allocatable,
target :: qtrc_ref(:,:,:,:)
148 real(
rp),
private,
allocatable,
target :: q_send_work(:,:,:,:)
149 real(
rp),
private,
allocatable,
target :: q_recv_work(:,:,:,:)
152 integer,
private :: now_step
153 logical,
private :: atmos_boundary_linear_v = .false.
154 logical,
private :: atmos_boundary_linear_h = .true.
155 real(
rp),
private :: atmos_boundary_exp_h = 2.0_rp
156 logical,
private :: atmos_boundary_online = .false.
157 logical,
private :: atmos_boundary_dens_adjust = .false.
158 real(
rp),
private :: atmos_boundary_dens_adjust_tau
160 logical,
private :: do_parent_process = .false.
161 logical,
private :: do_daughter_process = .false.
162 logical,
private :: l_bnd = .false.
165 real(
dp),
private :: masstot_now = 0.0_dp
166 real(
dp),
private :: massflx_now = 0.0_dp
167 real(
rp),
allocatable,
private :: areazuy_w(:,:), areazuy_e(:,:)
168 real(
rp),
allocatable,
private :: offset_time_fact(:)
169 real(
rp),
allocatable,
private :: mflux_offset_x(:,:,:,:)
170 real(
rp),
allocatable,
private :: mflux_offset_y(:,:,:,:)
171 real(
rp),
allocatable,
private,
target :: zero_x(:,:), zero_y(:,:)
210 namelist / param_atmos_boundary / &
211 atmos_boundary_type, &
212 atmos_boundary_in_basename, &
213 atmos_boundary_in_basename_add_num, &
214 atmos_boundary_in_number_of_files, &
215 atmos_boundary_in_check_coordinates, &
216 atmos_boundary_in_step_limit, &
217 atmos_boundary_in_aggregate, &
218 atmos_boundary_out_basename, &
219 atmos_boundary_out_title, &
220 atmos_boundary_out_dtype, &
221 atmos_boundary_out_aggregate, &
222 atmos_boundary_use_velz, &
223 atmos_boundary_use_velx, &
224 atmos_boundary_use_vely, &
225 atmos_boundary_use_pt, &
226 atmos_boundary_use_dens, &
227 atmos_boundary_use_qv, &
228 atmos_boundary_use_qhyd, &
229 atmos_boundary_use_chem, &
230 atmos_boundary_dens_adjust, &
231 atmos_boundary_dens_adjust_tau, &
232 atmos_boundary_value_velz, &
233 atmos_boundary_value_velx, &
234 atmos_boundary_value_vely, &
235 atmos_boundary_value_pt, &
236 atmos_boundary_value_qtrc, &
237 atmos_boundary_alphafact_dens, &
238 atmos_boundary_alphafact_velz, &
239 atmos_boundary_alphafact_velx, &
240 atmos_boundary_alphafact_vely, &
241 atmos_boundary_alphafact_pt, &
242 atmos_boundary_alphafact_qtrc, &
244 atmos_boundary_fracz, &
245 atmos_boundary_fracx, &
246 atmos_boundary_fracy, &
247 atmos_boundary_tauz, &
248 atmos_boundary_taux, &
249 atmos_boundary_tauy, &
250 atmos_boundary_linear_v, &
251 atmos_boundary_linear_h, &
252 atmos_boundary_exp_h, &
253 atmos_grid_nudging_uv, &
254 atmos_grid_nudging_pt, &
255 atmos_grid_nudging_qv, &
256 atmos_grid_nudging_tau
258 integer ::
k, i, j, iq
263 log_info(
"ATMOS_BOUNDARY_setup",*)
'Setup'
266 atmos_boundary_tauz = dt * 10.0_rp
267 atmos_boundary_taux = dt * 10.0_rp
268 atmos_boundary_tauy = dt * 10.0_rp
273 atmos_boundary_dens_adjust = .false.
274 atmos_boundary_dens_adjust_tau = -1.0_rp
276 atmos_grid_nudging_tau = 10.0_rp * 24.0_rp * 3600.0_rp
281 read(
io_fid_conf,nml=param_atmos_boundary,iostat=ierr)
283 log_info(
"ATMOS_BOUNDARY_setup",*)
'Not found namelist. Default used.'
284 elseif( ierr > 0 )
then
285 log_error(
"ATMOS_BOUNDARY_setup",*)
'Not appropriate names in namelist PARAM_ATMOS_BOUNDARY. Check!'
288 log_nml(param_atmos_boundary)
292 atmos_boundary_online = .false.
294 atmos_boundary_online = .true.
296 do_parent_process = .false.
297 do_daughter_process = .false.
298 if ( atmos_boundary_online )
then
300 do_parent_process = .true.
303 do_daughter_process = .true.
315 if( atmos_boundary_use_qhyd )
then
322 if( atmos_boundary_use_chem )
then
364 if ( atmos_boundary_type ==
'REAL' .OR. do_daughter_process )
then
372 allocate( dens_ref(
ka,
ia,
ja) )
373 allocate( velx_ref(
ka,
ia,
ja) )
374 allocate( vely_ref(
ka,
ia,
ja) )
375 allocate( pott_ref(
ka,
ia,
ja) )
377 dens_ref(:,:,:) = 0.0_rp
378 velx_ref(:,:,:) = 0.0_rp
379 vely_ref(:,:,:) = 0.0_rp
380 pott_ref(:,:,:) = 0.0_rp
381 qtrc_ref(:,:,:,:) = 0.0_rp
383 if ( atmos_boundary_use_velz )
then
384 allocate( velz_ref(
ka,
ia,
ja) )
385 velz_ref(:,:,:) = 0.0_rp
390 if ( do_daughter_process )
then
391 call atmos_boundary_initialize_online
393 if ( atmos_boundary_in_basename /=
'' )
then
394 call atmos_boundary_initialize_file
396 log_error(
"ATMOS_BOUNDARY_setup",*)
'You need specify ATMOS_BOUNDARY_IN_BASENAME'
401 if ( atmos_boundary_dens_adjust_tau <= 0.0_rp )
then
402 atmos_boundary_dens_adjust_tau = max(
real(update_dt,kind=
rp) / 6.0_rp, &
403 atmos_boundary_taux, atmos_boundary_tauy )
406 call atmos_boundary_setalpha
411 if ( atmos_boundary_dens_adjust )
then
412 allocate( areazuy_w(
ka,
ja), areazuy_e(
ka,
ja) )
413 allocate( mflux_offset_x(
ka,
ja,2,2), mflux_offset_y(
ka,
ia,2,2) )
414 allocate( zero_x(
ka,
ja), zero_y(
ka,
ia) )
426 mflux_offset_x(
k,j,:,:) = 0.0_rp
432 mflux_offset_y(
k,i,:,:) = 0.0_rp
452 elseif ( atmos_boundary_type ==
'NONE' )
then
456 elseif ( atmos_boundary_type ==
'CONST' )
then
458 call atmos_boundary_setalpha
462 elseif ( atmos_boundary_type ==
'INIT' )
then
464 call atmos_boundary_setalpha
468 elseif ( atmos_boundary_type ==
'OFFLINE' )
then
470 if ( atmos_boundary_in_basename /=
'' )
then
471 call atmos_boundary_read
473 log_error(
"ATMOS_BOUNDARY_setup",*)
'You need specify ATMOS_BOUNDARY_IN_BASENAME'
480 log_error(
"ATMOS_BOUNDARY_setup",*)
'unsupported ATMOS_BOUNDARY_TYPE. Check!', trim(atmos_boundary_type)
489 log_info(
"ATMOS_BOUNDARY_setup",*)
'Atmospheric boundary parameters '
490 log_info_cont(*)
'Atmospheric boundary type : ', atmos_boundary_type
492 log_info_cont(*)
'Is VELZ used in atmospheric boundary? : ', atmos_boundary_use_velz
493 log_info_cont(*)
'Is VELX used in atmospheric boundary? : ', atmos_boundary_use_velx
494 log_info_cont(*)
'Is VELY used in atmospheric boundary? : ', atmos_boundary_use_vely
495 log_info_cont(*)
'Is PT used in atmospheric boundary? : ', atmos_boundary_use_pt
496 log_info_cont(*)
'Is DENS used in atmospheric boundary? : ', atmos_boundary_use_dens
497 log_info_cont(*)
'Is QV used in atmospheric boundary? : ', atmos_boundary_use_qv
498 log_info_cont(*)
'Is QHYD used in atmospheric boundary? : ', atmos_boundary_use_qhyd
499 log_info_cont(*)
'Is CHEM used in atmospheric boundary? : ', atmos_boundary_use_chem
501 log_info_cont(*)
'Atmospheric boundary VELZ values : ', atmos_boundary_value_velz
502 log_info_cont(*)
'Atmospheric boundary VELX values : ', atmos_boundary_value_velx
503 log_info_cont(*)
'Atmospheric boundary VELY values : ', atmos_boundary_value_vely
504 log_info_cont(*)
'Atmospheric boundary PT values : ', atmos_boundary_value_pt
505 log_info_cont(*)
'Atmospheric boundary QTRC values : ', atmos_boundary_value_qtrc
508 log_info_cont(*)
'Atmospheric boundary z-fraction : ', atmos_boundary_fracz
509 log_info_cont(*)
'Atmospheric boundary x-fraction : ', atmos_boundary_fracx
510 log_info_cont(*)
'Atmospheric boundary y-fraction : ', atmos_boundary_fracy
511 log_info_cont(*)
'Atmospheric boundary z-relaxation time : ', atmos_boundary_tauz
512 log_info_cont(*)
'Atmospheric boundary x-relaxation time : ', atmos_boundary_taux
513 log_info_cont(*)
'Atmospheric boundary y-relaxation time : ', atmos_boundary_tauy
516 log_info_cont(*)
'Linear profile in vertically relax region : ', atmos_boundary_linear_v
517 log_info_cont(*)
'Linear profile in horizontally relax region : ', atmos_boundary_linear_h
518 log_info_cont(*)
'Non-linear factor in horizontally relax region : ', atmos_boundary_exp_h
520 log_info_cont(*)
'Online nesting for lateral boundary : ', atmos_boundary_online
521 log_info_cont(*)
'Does lateral boundary exist in this domain? : ', l_bnd
523 log_info_cont(*)
'Is grid nudging used for VELX & VELY? : ', atmos_grid_nudging_uv
524 log_info_cont(*)
'Is grid nudging used for POTT? : ', atmos_grid_nudging_pt
525 log_info_cont(*)
'Is grid nudging used for QV? : ', atmos_grid_nudging_qv
526 log_info_cont(*)
'Relaxation time for grid nudging : ', atmos_grid_nudging_tau
527 log_info_cont(*)
'Density adjustment : ', atmos_boundary_dens_adjust
528 if ( atmos_boundary_dens_adjust )
then
529 log_info_cont(*)
'Density relaxation time : ', atmos_boundary_dens_adjust_tau
563 real(
dp),
intent(in) :: time
568 if ( do_parent_process )
then
569 call atmos_boundary_firstsend( &
570 dens,
momz,
momx,
momy,
rhot,
qtrc(:,:,:,
qs_mp:
qe_mp),
qv,
qe )
575 if ( atmos_boundary_dens_adjust )
then
577 allocate( offset_time_fact(0:update_nstep) )
580 do n = 0, update_nstep
581 offset_time_fact(n) = 1.0_rp - cos( 2.0_rp * pi * ( n - 1 ) / update_nstep )
582 total = total + offset_time_fact(n)
584 total = total / update_nstep
586 do n = 0, update_nstep
587 offset_time_fact(n) = offset_time_fact(n) / total
592 if ( do_daughter_process )
then
595 if ( atmos_boundary_in_basename /=
'' )
then
600 elseif ( atmos_boundary_type ==
'CONST' )
then
602 call atmos_boundary_generate
604 elseif ( atmos_boundary_type ==
'INIT' )
then
606 call atmos_boundary_setinitval(
dens, &
614 if( atmos_boundary_out_basename /=
'' )
then
615 call atmos_boundary_write
634 subroutine atmos_boundary_var_fillhalo
683 end subroutine atmos_boundary_var_fillhalo
687 subroutine atmos_boundary_alpha_fillhalo
738 end subroutine atmos_boundary_alpha_fillhalo
742 subroutine atmos_boundary_setalpha
755 real(
rp) :: coef_z, alpha_z1, alpha_z2
756 real(
rp) :: coef_x, alpha_x1, alpha_x2
757 real(
rp) :: coef_y, alpha_y1, alpha_y2
758 real(
rp) :: alpha_zm, alpha_xm, alpha_ym
761 real(
rp) :: alpha_nug
763 integer :: i, j,
k, iq
767 atmos_boundary_fracz = max( min( atmos_boundary_fracz, 1.0_rp ), eps )
768 atmos_boundary_fracx = max( min( atmos_boundary_fracx, 1.0_rp ), eps )
769 atmos_boundary_fracy = max( min( atmos_boundary_fracy, 1.0_rp ), eps )
771 if ( atmos_boundary_tauz <= 0.0_rp )
then
774 coef_z = 1.0_rp / atmos_boundary_tauz
777 if ( atmos_boundary_taux <= 0.0_rp )
then
780 coef_x = 1.0_rp / atmos_boundary_taux
783 if ( atmos_boundary_tauy <= 0.0_rp )
then
786 coef_y = 1.0_rp / atmos_boundary_tauy
789 if ( atmos_grid_nudging_tau <= 0.0_rp )
then
792 alpha_nug = 1.0_rp / atmos_grid_nudging_tau
817 if ( ee1 <= 1.0_rp - atmos_boundary_fracz )
then
820 ee1 = ( ee1 - 1.0_rp + atmos_boundary_fracz ) / atmos_boundary_fracz
824 if ( ee2 <= 1.0_rp - atmos_boundary_fracz )
then
827 ee2 = ( ee2 - 1.0_rp + atmos_boundary_fracz ) / atmos_boundary_fracz
830 if ( .not. atmos_boundary_linear_v )
then
831 if ( ee1 > 0.0_rp .AND. ee1 <= 0.5_rp )
then
832 ee1 = 0.5_rp * ( 1.0_rp - cos( ee1*pi ) )
833 elseif( ee1 > 0.5_rp .AND. ee1 <= 1.0_rp )
then
834 ee1 = 0.5_rp * ( 1.0_rp + sin( (ee1-0.5_rp)*pi ) )
836 if ( ee2 > 0.0_rp .AND. ee2 <= 0.5_rp )
then
837 ee2 = 0.5_rp * ( 1.0_rp - cos( ee2*pi ) )
838 elseif( ee2 > 0.5_rp .AND. ee2 <= 1.0_rp )
then
839 ee2 = 0.5_rp * ( 1.0_rp + sin( (ee2-0.5_rp)*pi ) )
843 alpha_z1 = coef_z * ee1
844 alpha_z2 = coef_z * ee2
845 alpha_zm = ee1 / atmos_boundary_dens_adjust_tau
849 if ( ee1 <= 1.0_rp - atmos_boundary_fracx )
then
852 ee1 = ( ee1 - 1.0_rp + atmos_boundary_fracx ) / atmos_boundary_fracx
856 if ( ee2 <= 1.0_rp - atmos_boundary_fracx )
then
859 ee2 = ( ee2 - 1.0_rp + atmos_boundary_fracx ) / atmos_boundary_fracx
862 if ( .not. atmos_boundary_linear_h )
then
863 ee1 = ee1 * exp( -(1.0_rp-ee1) * atmos_boundary_exp_h )
864 ee2 = ee2 * exp( -(1.0_rp-ee2) * atmos_boundary_exp_h )
867 alpha_x1 = coef_x * ee1
868 alpha_x2 = coef_x * ee2
869 alpha_xm = ee1 / atmos_boundary_dens_adjust_tau
873 if ( ee1 <= 1.0_rp - atmos_boundary_fracy )
then
876 ee1 = ( ee1 - 1.0_rp + atmos_boundary_fracy ) / atmos_boundary_fracy
880 if ( ee2 <= 1.0_rp - atmos_boundary_fracy )
then
883 ee2 = ( ee2 - 1.0_rp + atmos_boundary_fracy ) / atmos_boundary_fracy
886 if ( .not. atmos_boundary_linear_h )
then
887 ee1 = ee1 * exp( -(1.0_rp-ee1) * atmos_boundary_exp_h )
888 ee2 = ee2 * exp( -(1.0_rp-ee2) * atmos_boundary_exp_h )
891 alpha_y1 = coef_y * ee1
892 alpha_y2 = coef_y * ee2
893 alpha_ym = ee1 / atmos_boundary_dens_adjust_tau
897 if ( atmos_boundary_use_velz )
then
902 if ( atmos_boundary_dens_adjust )
then
915 if ( atmos_boundary_use_dens )
then
920 if ( atmos_boundary_use_velz )
then
925 if ( atmos_boundary_use_velx )
then
930 if ( atmos_boundary_use_vely )
then
935 if ( atmos_boundary_use_pt )
then
943 if ( atmos_boundary_use_qv )
then
956 if ( atmos_grid_nudging_uv )
then
960 if ( atmos_grid_nudging_pt )
then
963 if ( atmos_grid_nudging_qv )
then
972 call atmos_boundary_alpha_fillhalo
975 end subroutine atmos_boundary_setalpha
979 subroutine atmos_boundary_setinitval( &
980 DENS, MOMZ, MOMX, MOMY, RHOT, QTRC )
984 real(
rp),
intent(in) :: momz(
ka,
ia,
ja)
985 real(
rp),
intent(in) :: momx(
ka,
ia,
ja)
986 real(
rp),
intent(in) :: momy(
ka,
ia,
ja)
987 real(
rp),
intent(in) :: rhot(
ka,
ia,
ja)
990 integer :: i, j,
k, iq, iqb
1046 call atmos_boundary_var_fillhalo
1051 end subroutine atmos_boundary_setinitval
1055 subroutine atmos_boundary_read
1060 file_cartesc_check_coordinates, &
1061 file_cartesc_read, &
1070 call file_cartesc_open( atmos_boundary_in_basename, fid, aggregate=atmos_boundary_in_aggregate )
1072 if ( atmos_boundary_in_check_coordinates )
then
1073 call file_cartesc_check_coordinates( fid, atmos=.true. )
1076 if ( atmos_boundary_use_dens &
1077 .OR. atmos_boundary_use_velz &
1078 .OR. atmos_boundary_use_velx &
1079 .OR. atmos_boundary_use_vely &
1080 .OR. atmos_boundary_use_pt &
1088 if ( atmos_boundary_use_dens )
then
1096 if ( atmos_boundary_use_velz )
then
1105 if ( atmos_boundary_use_velx )
then
1114 if ( atmos_boundary_use_vely )
then
1123 if ( atmos_boundary_use_pt )
then
1147 call atmos_boundary_var_fillhalo
1148 call atmos_boundary_alpha_fillhalo
1151 end subroutine atmos_boundary_read
1155 subroutine atmos_boundary_write
1160 file_cartesc_write_var, &
1165 integer :: vid_dens, vid_a_dens
1166 integer :: vid_velz, vid_a_velz
1167 integer :: vid_velx, vid_a_velx
1168 integer :: vid_vely, vid_a_vely
1169 integer :: vid_pott, vid_a_pott
1175 atmos_boundary_out_dtype, &
1177 aggregate = atmos_boundary_out_aggregate )
1179 if ( atmos_boundary_use_dens &
1180 .OR. atmos_boundary_use_velz &
1181 .OR. atmos_boundary_use_velx &
1182 .OR. atmos_boundary_use_vely &
1183 .OR. atmos_boundary_use_pt &
1185 call file_cartesc_def_var( fid,
'DENS',
'Reference Density',
'kg/m3',
'ZXY', atmos_boundary_out_dtype, vid_dens )
1190 if ( atmos_boundary_use_dens .OR. l_bnd )
then
1191 call file_cartesc_def_var( fid,
'ALPHA_DENS',
'Alpha for DENS',
'1',
'ZXY', atmos_boundary_out_dtype, vid_a_dens )
1196 if ( atmos_boundary_use_velz )
then
1197 call file_cartesc_def_var( fid,
'VELZ',
'Reference Velocity w',
'm/s',
'ZHXY', atmos_boundary_out_dtype, vid_velz )
1198 call file_cartesc_def_var( fid,
'ALPHA_VELZ',
'Alpha for VELZ',
'1',
'ZHXY', atmos_boundary_out_dtype, vid_a_velz )
1203 if ( atmos_boundary_use_velx .OR. l_bnd )
then
1204 call file_cartesc_def_var( fid,
'VELX',
'Reference Velocity u',
'm/s',
'ZXHY', atmos_boundary_out_dtype, vid_velx )
1205 call file_cartesc_def_var( fid,
'ALPHA_VELX',
'Alpha for VELX',
'1',
'ZXHY', atmos_boundary_out_dtype, vid_a_velx )
1210 if ( atmos_boundary_use_vely .OR. l_bnd )
then
1211 call file_cartesc_def_var( fid,
'VELY',
'Reference Velocity y',
'm/s',
'ZXYH', atmos_boundary_out_dtype, vid_vely )
1212 call file_cartesc_def_var( fid,
'ALPHA_VELY',
'Alpha for VELY',
'1',
'ZXYH', atmos_boundary_out_dtype, vid_a_vely )
1217 if ( atmos_boundary_use_pt .OR. l_bnd )
then
1218 call file_cartesc_def_var( fid,
'PT',
'Reference PT',
'K',
'ZXY', atmos_boundary_out_dtype, vid_pott )
1219 call file_cartesc_def_var( fid,
'ALPHA_PT',
'Alpha for PT',
'1',
'ZXY', atmos_boundary_out_dtype, vid_a_pott )
1236 if ( vid_dens > 0 )
then
1240 if ( vid_a_dens > 0 )
then
1244 if ( vid_velz > 0 )
then
1249 if ( vid_velx > 0 )
then
1254 if ( vid_vely > 0 )
then
1259 if ( vid_pott > 0 )
then
1265 if ( vid_qtrc(iqb) > 0 )
then
1276 end subroutine atmos_boundary_write
1280 subroutine atmos_boundary_generate
1285 integer :: i, j,
k, iq
1307 call atmos_boundary_var_fillhalo
1310 end subroutine atmos_boundary_generate
1314 subroutine atmos_boundary_initialize_file
1318 file_external_input_regist
1323 character(len=4),
parameter :: vars_name(4) = (/
'DENS',
'VELX',
'VELY',
'PT ' /)
1326 integer :: n, iq, iqb
1329 call file_external_input_regist( atmos_boundary_in_basename, &
1330 atmos_boundary_in_basename_add_num, &
1331 atmos_boundary_in_number_of_files, &
1334 .false., .false., .false., 0, 0.0_rp, &
1335 check_coordinates = atmos_boundary_in_check_coordinates, &
1336 step_limit = atmos_boundary_in_step_limit, &
1337 update_dt = update_dt )
1340 if ( update_dt <= 0.0_dp )
then
1341 log_error(
"ATMOS_BOUNDARY_initialize_file",*)
'Time in the file is invalid'
1344 update_nstep = nint( update_dt /
time_dtsec )
1345 if ( abs(update_nstep *
time_dtsec - update_dt) > 1e-10_dp )
then
1346 log_error(
"ATMOS_BOUNDARY_initialize_file",*)
'Time step in the file is not multiple of DT'
1353 call file_external_input_regist( atmos_boundary_in_basename, &
1354 atmos_boundary_in_basename_add_num, &
1355 atmos_boundary_in_number_of_files, &
1358 .false., .false., .false., 0, 0.0_rp, &
1359 check_coordinates = atmos_boundary_in_check_coordinates, &
1360 step_limit = atmos_boundary_in_step_limit )
1363 if ( atmos_boundary_use_velz )
then
1377 end subroutine atmos_boundary_initialize_file
1384 file_external_input_get_ref, &
1387 real(DP),
intent(in) :: time
1392 if ( atmos_boundary_dens_adjust )
then
1393 call file_external_input_get_ref(
'DENS', dens_ref(:,:,:), error,
i_prev )
1394 call file_external_input_get_ref(
'VELX', velx_ref(:,:,:), error,
i_prev )
1395 call file_external_input_get_ref(
'VELY', vely_ref(:,:,:), error,
i_prev )
1400 call atmos_boundary_update_file( time )
1407 subroutine atmos_boundary_initialize_online
1421 update_nstep = nint( update_dt /
time_dtsec )
1422 if ( update_nstep *
time_dtsec /= update_dt )
then
1423 log_error(
"ATMOS_BOUNDARY_initialize_online",*)
'DT of the parent is not multiple of the DT'
1427 log_error(
"ATMOS_BOUNDARY_initialize_online",*)
'DURATION must be the same as that of the parent'
1432 log_error(
"ATMOS_BOUNDARY_initialize_online",*)
'ONLINE_RECV_QA exceeds BND_QA'
1433 log_error_cont(*)
'This must not be occur.'
1434 log_error_cont(*)
'Please send your configuration file to SCALE develop member.'
1441 end subroutine atmos_boundary_initialize_online
1453 file_external_input_regist
1455 real(DP),
intent(in) :: time
1462 call atmos_boundary_update_online_daughter( time, .true., .true. )
1464 nstep = parent_nstep + 1
1466 call file_external_input_regist(
'DENS', &
1473 call file_external_input_regist(
'VELX', &
1480 call file_external_input_regist(
'VELY', &
1487 call file_external_input_regist(
'PT', &
1497 call file_external_input_regist(
tracer_name(iq), &
1498 qtrc_ref(:,:,:,iqb), &
1505 if ( atmos_boundary_use_velz )
then
1506 call file_external_input_regist(
'VELZ', &
1515 call atmos_boundary_update_online_daughter( time, .false., .true. )
1522 subroutine atmos_boundary_firstsend( &
1523 DENS, MOMZ, MOMX, MOMY, RHOT, QTRC, QV, Qe )
1531 real(RP),
intent(in) :: DENS(KA,IA,JA)
1532 real(RP),
intent(in) :: MOMZ(KA,IA,JA)
1533 real(RP),
intent(in) :: MOMX(KA,IA,JA)
1534 real(RP),
intent(in) :: MOMY(KA,IA,JA)
1535 real(RP),
intent(in) :: RHOT(KA,IA,JA)
1536 real(RP),
intent(in) :: QTRC(KA,IA,JA,QA_MP)
1537 real(RP),
intent(in) :: QV (KA,IA,JA)
1538 real(RP),
intent(in) :: Qe (KA,IA,JA,N_HYD)
1542 if ( do_parent_process )
then
1544 call atmos_boundary_send( dens, momz, momx, momy, rhot, qtrc, qv, qe )
1548 end subroutine atmos_boundary_firstsend
1562 if ( do_parent_process )
then
1566 if ( do_daughter_process )
then
1595 deallocate( dens_ref )
1596 deallocate( velx_ref )
1597 deallocate( vely_ref )
1598 deallocate( pott_ref )
1599 deallocate( qtrc_ref )
1601 if ( atmos_boundary_use_velz )
then
1603 deallocate( velz_ref )
1606 if ( atmos_boundary_dens_adjust )
then
1608 deallocate( areazuy_w, areazuy_e )
1609 deallocate( mflux_offset_x, mflux_offset_y )
1610 deallocate( zero_x )
1611 deallocate( zero_y )
1615 if (
allocated( q_send_work ) )
then
1617 deallocate( q_send_work )
1619 if (
allocated( q_recv_work ) )
then
1621 deallocate( q_recv_work )
1639 real(
dp),
intent(in) :: time
1645 if ( do_daughter_process )
then
1646 call atmos_boundary_update_online_daughter( time, .false., .false. )
1648 call atmos_boundary_update_file( time )
1653 elseif ( do_parent_process )
then
1656 log_error(
"ATMOS_BOUNDARY_driver_update",*)
'[BUG] invalid path'
1668 if ( do_daughter_process )
then
1696 if ( do_parent_process )
then
1698 call atmos_boundary_update_online_parent(
dens,
momz,
momx,
momy,
rhot,
qtrc(:,:,:,
qs_mp:
qe_mp),
qv,
qe )
1709 subroutine atmos_boundary_update( &
1714 file_external_input_update
1716 real(
dp),
intent(in) :: time
1723 log_error(
"ATMOS_BOUNDARY_update",*)
'Failed to read data: DENS'
1729 log_error(
"ATMOS_BOUNDARY_update",*)
'Failed to read data: VELX'
1735 log_error(
"ATMOS_BOUNDARY_update",*)
'Failed to read data: VELY'
1741 log_error(
"ATMOS_BOUNDARY_update",*)
'Failed to read data: PT'
1745 if ( do_daughter_process .and. atmos_boundary_use_velz )
then
1748 log_error(
"ATMOS_BOUNDARY_update",*)
'Failed to read data: VELZ'
1758 log_error(
"ATMOS_BOUNDARY_update",*)
'Failed to read data: ', trim(
tracer_name(iq))
1764 call atmos_boundary_var_fillhalo
1767 end subroutine atmos_boundary_update
1771 subroutine atmos_boundary_update_file( &
1774 file_external_input_get_ref
1776 real(
dp),
intent(in) :: time
1781 call atmos_boundary_update( time )
1783 if ( atmos_boundary_dens_adjust )
then
1784 call file_external_input_get_ref(
'DENS', dens_ref(:,:,:), error )
1785 call file_external_input_get_ref(
'VELX', velx_ref(:,:,:), error )
1786 call file_external_input_get_ref(
'VELY', vely_ref(:,:,:), error )
1792 end subroutine atmos_boundary_update_file
1796 subroutine atmos_boundary_update_online_parent( &
1815 real(
rp),
intent(in) :: momz(
ka,
ia,
ja)
1816 real(
rp),
intent(in) :: momx(
ka,
ia,
ja)
1817 real(
rp),
intent(in) :: momy(
ka,
ia,
ja)
1818 real(
rp),
intent(in) :: rhot(
ka,
ia,
ja)
1820 real(
rp),
intent(in) :: qv (
ka,
ia,
ja)
1825 log_info(
"ATMOS_BOUNDARY_update_online_parent",*)
"ATMOS BOUNDARY update online: PARENT"
1831 call atmos_boundary_send(
dens, momz, momx, momy, rhot,
qtrc, qv, qe )
1834 end subroutine atmos_boundary_update_online_parent
1838 subroutine atmos_boundary_update_online_daughter( &
1846 file_external_input_put_ref
1848 real(
dp),
intent(in) :: time
1849 logical,
intent(in) :: init
1850 logical,
intent(in) :: force
1857 log_info(
"ATMOS_BOUNDARY_update_online_daughter",
'(1X,A,I5)')
'ATMOS BOUNDARY update online: DAUGHTER'
1859 if ( .not. force )
then
1869 call atmos_boundary_recv
1874 if ( atmos_boundary_dens_adjust )
then
1879 if ( .not. init )
then
1880 call file_external_input_put_ref(
'DENS', dens_ref(:,:,:), error )
1881 call file_external_input_put_ref(
'VELX', velx_ref(:,:,:), error )
1882 call file_external_input_put_ref(
'VELY', vely_ref(:,:,:), error )
1883 call file_external_input_put_ref(
'PT', pott_ref(:,:,:), error )
1887 call file_external_input_put_ref(
tracer_name(iq), qtrc_ref(:,:,:,iqb), error )
1891 if ( atmos_boundary_use_velz )
then
1892 call file_external_input_put_ref(
'VELZ', velz_ref(:,:,:), error )
1898 if ( .not. init )
call atmos_boundary_update( time )
1902 end subroutine atmos_boundary_update_online_daughter
1906 subroutine atmos_boundary_send( &
1907 DENS, MOMZ, MOMX, MOMY, RHOT, QTRC, QV, Qe )
1920 real(
rp),
intent(in) :: momz(
ka,
ia,
ja)
1921 real(
rp),
intent(in) :: momx(
ka,
ia,
ja)
1922 real(
rp),
intent(in) :: momy(
ka,
ia,
ja)
1923 real(
rp),
intent(in) :: rhot(
ka,
ia,
ja)
1925 real(
rp),
intent(in) :: qv (
ka,
ia,
ja)
1929 real(
rp),
pointer :: q(:,:,:,:)
1939 q(:,:,:,1) = qv(:,:,:)
1943 q(:,:,:,iq) = qe(:,:,:,iq-1)
1960 end subroutine atmos_boundary_send
1964 subroutine atmos_boundary_recv
1976 real(
rp),
pointer :: q(:,:,:,:)
1994 q(:,:,:,1), q(:,:,:,2:), &
1999 end subroutine atmos_boundary_recv
2017 integer :: i, j, k, iq, iqb
2070 if ( atmos_boundary_use_velz )
then
2164 if ( atmos_boundary_use_velz )
then
2232 if ( atmos_boundary_use_velz )
then
2314 if ( atmos_boundary_use_velz )
then
2344 ATMOS_BOUNDARY_DENS, &
2345 ATMOS_BOUNDARY_VELZ, &
2346 ATMOS_BOUNDARY_VELX, &
2347 ATMOS_BOUNDARY_VELY, &
2348 ATMOS_BOUNDARY_POTT, &
2349 ATMOS_BOUNDARY_QTRC )
2355 real(RP),
intent(in) :: ATMOS_BOUNDARY_DENS(KA,IA,JA)
2356 real(RP),
intent(in) :: ATMOS_BOUNDARY_VELZ(KA,IA,JA)
2357 real(RP),
intent(in) :: ATMOS_BOUNDARY_VELX(KA,IA,JA)
2358 real(RP),
intent(in) :: ATMOS_BOUNDARY_VELY(KA,IA,JA)
2359 real(RP),
intent(in) :: ATMOS_BOUNDARY_POTT(KA,IA,JA)
2360 real(RP),
intent(in) :: ATMOS_BOUNDARY_QTRC(KA,IA,JA,BND_QA)
2364 call file_history_in( atmos_boundary_dens(:,:,:),
'DENS_BND',
'Boundary Density',
'kg/m3' )
2365 call file_history_in( atmos_boundary_velz(:,:,:),
'VELZ_BND',
'Boundary velocity z-direction',
'm/s', dim_type=
'ZHXY' )
2366 call file_history_in( atmos_boundary_velx(:,:,:),
'VELX_BND',
'Boundary velocity x-direction',
'm/s', dim_type=
'ZXHY' )
2367 call file_history_in( atmos_boundary_vely(:,:,:),
'VELY_BND',
'Boundary velocity y-direction',
'm/s', dim_type=
'ZXYH' )
2368 call file_history_in( atmos_boundary_pott(:,:,:),
'PT_BND',
'Boundary potential temperature',
'K' )
2372 call file_history_in( atmos_boundary_qtrc(:,:,:,iqb), trim(
tracer_name(iq))//
'_BND', &
2400 real(DP) :: masstot, masstot_current
2402 real(DP) :: offset_band, offset_bias
2404 real(DP) :: flx_w, flx_e, flx_s, flx_n
2405 real(DP) :: ref_w, ref_e, ref_s, ref_n
2407 real(RP),
target :: work_x(KA,JA), work_y(KA,IA)
2408 real(RP),
pointer :: ptr(:,:)
2415 call statistics_total( ka,
ks,
ke, ia,
is,
ie, ja,
js,
je, &
2418 vol(:,:,:), totvol, &
2419 log_suppress = .true., global = .true., &
2435 work_x(k,j) = velx_ref(k,
is-1,j) &
2436 * ( dens_ref(k,
is-1,j) + dens_ref(k,
is,j) ) * 0.5_rp
2444 call statistics_total( ka,
ks,
ke, ja,
js,
je, &
2445 ptr(:,:),
"MFLUX_bnd_w", &
2446 areazuy_w(:,:), totareazuy_x(
is-1), &
2447 log_suppress = .true., global = .true., &
2454 work_x(k,j) = dens_ref(k,
is,j)
2459 call statistics_total( ka,
ks,
ke, ja,
js,
je, &
2460 ptr(:,:),
"DENS_ref_w", &
2461 areazuy_w(:,:), totareazuy_x(
is-1), &
2462 log_suppress = .true., global = .true., &
2471 work_x(k,j) = velx_ref(k,
ie,j) &
2472 * ( dens_ref(k,
ie,j) + dens_ref(k,
ie+1,j) ) * 0.5_rp
2480 call statistics_total( ka,
ks,
ke, ja,
js,
je, &
2481 ptr(:,:),
"MFLUX_bnd_e", &
2482 areazuy_e(:,:), totareazuy_x(
ie), &
2483 log_suppress = .true., global = .true., &
2490 work_x(k,j) = dens_ref(k,
ie,j)
2495 call statistics_total( ka,
ks,
ke, ja,
js,
je, &
2496 ptr(:,:),
"DENS_ref_e", &
2497 areazuy_e(:,:), totareazuy_x(
ie), &
2498 log_suppress = .true., global = .true., &
2507 work_y(k,i) = vely_ref(k,i,
js-1) &
2508 * ( dens_ref(k,i,
js-1) + dens_ref(k,i,
js) ) * 0.5_rp
2516 call statistics_total( ka,
ks,
ke, ia,
is,
ie, &
2517 ptr(:,:),
"MFLUX_bnd_s", &
2518 areazxv_y(:,:,
js-1), totareazxv_y(
js-1), &
2519 log_suppress = .true., global = .true., &
2526 work_y(k,i) = dens_ref(k,i,
js)
2531 call statistics_total( ka,
ks,
ke, ia,
is,
ie, &
2532 ptr(:,:),
"DENS_ref_s", &
2533 areazxv_y(:,:,
js-1), totareazxv_y(
js-1), &
2534 log_suppress = .true., global = .true., &
2543 work_y(k,i) = vely_ref(k,i,
je) &
2544 * ( dens_ref(k,i,
je) + dens_ref(k,i,
je+1) ) * 0.5_rp
2552 call statistics_total( ka,
ks,
ke, ia,
is,
ie, &
2553 ptr(:,:),
"MFLX_bnd_n", &
2554 areazxv_y(:,:,
je), totareazxv_y(
je), &
2555 log_suppress = .true., global = .true., &
2562 work_y(k,i) = dens_ref(k,i,
je)
2567 call statistics_total( ka,
ks,
ke, ia,
is,
ie, &
2568 ptr(:,:),
"DENS_ref_n", &
2569 areazxv_y(:,:,
je), totareazxv_y(
je), &
2570 log_suppress = .true., global = .true., &
2573 massflx = flx_w - flx_e + flx_s - flx_n
2575 offset_band = ( masstot - masstot_now ) / update_dt &
2576 - ( massflx + massflx_now ) * 0.5_dp
2579 log_info(
"ATMOS_BOUNDARY_calc_mass",*)
"Offset_band is: ", offset_band,
"(", masstot, masstot_now, massflx, massflx_now,
")"
2581 ref_tot = ref_w + ref_e + ref_s + ref_n
2582 offset_band = offset_band / ref_tot
2585 log_info_cont(*)
" per dens ", offset_band
2593 mflux_offset_x(k,j,1,1) = offset_band * dens_ref(k,
is,j)
2604 mflux_offset_x(k,j,2,1) = - offset_band * dens_ref(k,
ie,j)
2615 mflux_offset_y(k,i,1,1) = offset_band * dens_ref(k,i,
js)
2626 mflux_offset_y(k,i,2,1) = - offset_band * dens_ref(k,i,
je)
2633 masstot_now = masstot
2634 massflx_now = massflx
2643 integer :: k, i, j, n