63 REAL(wp) :: t1 , t2 , t3
66 INTEGER :: st1 , st2 , st3 , cr , cm
68 REAL(wp) :: dt_old , dt_old_old
70 LOGICAL :: steady_state
78 REAL(wp) :: x1 , x2 , x3 , xt
79 REAL(wp) :: y1 , y2 , y3 , yt
80 REAL(wp) :: x_new_source
81 REAL(wp) :: y_new_source
82 REAL(wp) :: r_new_source
83 REAL(wp) :: r_old_source
84 INTEGER :: j1 , j2 , j3
85 INTEGER :: k1 , k2 , k3
87 REAL(wp) :: max_up_dist
88 REAL(wp) :: max_cw_distL
89 REAL(wp) :: max_cw_distR
91 REAL(wp) :: csq1 , csq2 , csq3
94 REAL(wp) :: h_tot , h_avg
97 REAL(wp) :: x_upw , y_upw
98 REAL(wp) :: d_upw_nbl , d_upw_umb
100 integer,
allocatable :: positive_values(:)
102 LOGICAL :: use_openmp = .false.
104 INTEGER :: i_multigrid
107 CHARACTER(LEN=30) :: swu_file
108 CHARACTER(LEN=30) :: umb_file
110 INTEGER,
PARAMETER :: swu_unit = 19
111 INTEGER,
PARAMETER :: umb_unit = 20
113 CHARACTER(LEN=20) :: description
118 WRITE(*,*)
'---------------------' 119 WRITE(*,*)
'SW_UMBRELLA 1.0' 120 WRITE(*,*)
'---------------------' 125 IF ( .NOT. use_openmp)
THEN 127 print *,
"Non-OpenMP simulation" 133 IF ( verbose_level .GE. 0 )
WRITE(*,*)
'Number of threads used', n_threads
138 WRITE(*,*)
'u_atm',u_atm_umbl
139 WRITE(*,*)
'v_atm',v_atm_umbl
144 CALL system_clock(count_rate=cr)
145 CALL system_clock(count_max=cm)
149 CALL system_clock (st1)
153 CALL init_problem_param
157 CALL allocate_solver_variables
159 CALL compute_cell_fract
161 IF ( i_multigrid .GT. 1 )
THEN 169 umb_file = trim(run_name)//
'.umb' 171 OPEN(umb_unit,file=umb_file,status=
'unknown',form=
'formatted')
173 x_upw = x_source - r_source * u_atm_umbl / sqrt( u_atm_umbl**2 + &
175 y_upw = y_source - r_source * v_atm_umbl / sqrt( u_atm_umbl**2 + &
178 d_upw_nbl = sqrt(x_upw**2 + y_upw**2)
181 WRITE(umb_unit,306) t, 3.1415_wp * r_source**2 , d_upw_nbl
183 305
FORMAT( 5x,
' time (s)', 11x,
' area (m2)',11x,
'upw distance (m)')
185 306
FORMAT((7x,f14.4,16x,es11.3e3,16x,es11.3e3))
187 steady_state = .false.
189 solve_mask(2:comp_cells_x-1,2:comp_cells_y-1) = .true.
193 IF ( verbose_level .GE. 0 )
THEN 196 WRITE(*,*)
'******** START COMPUTATION *********' 201 IF ( verbose_level .GE. 1 )
THEN 203 WRITE(*,*)
'Min q(1,:,:)=',minval(q(1,:,:))
204 WRITE(*,*)
'Max q(1,:,:)=',maxval(q(1,:,:))
206 WRITE(*,*)
'SUM(q(1,:,:)=',sum(q(1,:,:))
215 DO k = 1,comp_cells_y
217 DO j = 1,comp_cells_x
219 IF ( q(1,j,k) .GT. 0.0_wp )
THEN 233 CALL output_solution(t,steady_state)
235 IF ( sum(q(1,:,:)) .EQ. 0.0_wp ) t_steady = t_output
237 x_new_source = x_source
238 y_new_source = y_source
239 r_new_source = r_source
240 r_old_source = r_source
242 WRITE(*,*) dx*dy*count(q(1,:,:).GT.1.e-5_wp)
243 IF ( verbose_level .GE. 0.0_wp )
THEN 245 WRITE(*,fmt=
"(A3,F10.4,A5,F9.5,A9,ES11.3E3,A11,ES11.3E3,A9,ES11.3E3,A9,ES11.3E3)") &
246 't =',t,
'dt =',dt0, &
247 ' volume = ',dx*dy*sum(qp(1,:,:)) , &
248 ' area = ',dx*dy*count(q(1,:,:).GT.1.e-5_wp),
' xnew =',x_new_source, &
249 ' rnew =',r_new_source
253 CALL system_clock (st2)
255 time_loop:
DO WHILE ( ( t .LT. t_end ) .AND. ( t .LT. t_steady ) )
259 IF ( verbose_level .GE. 1 )
THEN 261 WRITE(*,*)
'cells to solve and reconstruct:' , count(solve_mask)
267 IF ( t+dt .GT. t_end ) dt = t_end - t
268 IF ( t+dt .GT. t_output ) dt = t_output - t
270 dt = min(dt,1.1_wp * 0.5_wp * ( dt_old + dt_old_old ) )
281 max_up_dist = r_source
282 x1 = x_source - r_source*u_atm_umbl / ( sqrt( u_atm_umbl**2+v_atm_umbl**2 ) )
283 y1 = y_source - r_source*v_atm_umbl / ( sqrt( u_atm_umbl**2+v_atm_umbl**2 ) )
284 max_cw_distl = 0.0_wp
285 max_cw_distr = 0.0_wp
292 IF ( q(1,j,k) .GT. 0.0_wp )
THEN 296 IF ( qp(1,j,k) .GE. 10.0_wp )
THEN 298 upwind_dist(j,k) = - ( u_atm_umbl * ( x_comp(j) - x_source ) + &
299 v_atm_umbl * ( y_comp(k) - y_source ) ) &
300 / ( sqrt( u_atm_umbl**2 + v_atm_umbl**2 ) )
303 u_atm_umbl * ( y_comp(k) - y_source ) ) &
304 / ( sqrt( u_atm_umbl**2 + v_atm_umbl**2 ) )
339 qp(1:
n_vars+2,j,k) = 0.0_wp
350 IF ( abs( y1 - y2 ) .LT. abs( y1 - y3 ) )
THEN 367 top = ( y2 - y3 ) * ( csq1 - csq2 ) - ( y1 - y2 ) * ( csq2 - csq3 )
368 bot = ( x1 - x2 ) * ( y2 - y3 ) - ( x2 - x3 ) * ( y1 - y2 )
370 x_new_source = 0.5_wp * top / bot
371 y_new_source = 0.5_wp * ( csq1 - csq2 - 2.0_wp * x_new_source * &
372 ( x1 - x2 ) ) / ( y1 - y2 )
373 r_new_source = sqrt( ( x1 - x_new_source )**2 + ( y1 - y_new_source )**2 )
375 IF ( verbose_level .GE. 0 )
THEN 377 WRITE(*,fmt=
"(A3,F10.4,A5,F9.5,A9,ES11.3E3,A11,ES11.3E3,A9,ES11.3E3,A9,ES11.3E3,A9,ES11.3E3)")&
378 't =' , t ,
'dt =' , dt ,
' volume = ' , dx*dy*sum(qp(1,:,:)) , &
379 ' area = ' , dx*dy*count(q(1,:,:).GT.1.e-2_wp) ,
' xnew =' , &
380 x_new_source ,
' ynew =' , y_new_source ,
' rnew =' , r_new_source
386 IF ( ( t .GE. t_output ) .OR. ( t .GE. t_end ) )
THEN 389 CALL system_clock(st3)
391 IF ( verbose_level .GE. 0.0_wp )
THEN 393 WRITE(*,*)
'Time taken by iterations is',t3-t2,
'seconds' 394 WRITE(*,*)
'Elapsed real time = ', dble( st3-st2 ) / rate,
'seconds' 398 CALL output_solution(t,steady_state)
400 x_upw = x_new_source - r_new_source * u_atm_umbl / sqrt( u_atm_umbl**2 + &
402 y_upw = y_new_source - r_new_source * v_atm_umbl / sqrt( u_atm_umbl**2 + &
405 d_upw_umb = sqrt(x_upw**2 + y_upw**2)
407 WRITE(umb_unit,306) t, dx*dy*count(q(1,:,:).GT.1.e-2_wp) , d_upw_umb
410 IF (
steady_flag .AND. ( r_new_source .EQ. r_old_source ) )
THEN 412 WRITE(*,*)
'STEADY UMBRELLA REACHED' 416 r_old_source = r_new_source
420 solve_mask(2:comp_cells_x-1,2:comp_cells_y-1) = .false.
424 steady_state = .true.
425 CALL output_solution(t,steady_state)
438 IF ( q(1,j,k) .GT. 0.0_wp )
THEN 442 IF ( ( x_comp(j)-x_new_source )**2 + ( y_comp(k)-y_new_source )**2 &
443 .LE. r_new_source**2 )
THEN 445 h_tot = h_tot + qp(1,j,k)
454 h_avg = h_tot / n_tot
456 CALL deallocate_solver_variables
462 CALL system_clock(st3)
464 WRITE(*,fmt=
"(A9,ES11.3E3,A9,ES11.3E3,A9,ES11.3E3)")
' xold =', x_source, &
465 ' yold =',y_source,
' rold =',r_source
467 x_upw = x_source - r_source * u_atm_umbl / sqrt( u_atm_umbl**2 + &
469 y_upw = y_source - r_source * v_atm_umbl / sqrt( u_atm_umbl**2 + &
472 d_upw_nbl = sqrt(x_upw**2 + y_upw**2)
474 WRITE(*,*)
'Upwind plume point',x_upw,y_upw
475 WRITE(*,*)
'Upwind plume distance',d_upw_nbl
478 WRITE(*,fmt=
"(A9,ES11.3E3,A9,ES11.3E3,A9,ES11.3E3,A9,ES11.3E3)")
' xnew =', &
479 x_new_source,
' ynew =',y_new_source,
' rnew =',r_new_source,
' havg =',&
482 x_upw = x_new_source - r_new_source * u_atm_umbl / sqrt( u_atm_umbl**2 + &
484 y_upw = y_new_source - r_new_source * v_atm_umbl / sqrt( u_atm_umbl**2 + &
487 d_upw_umb = sqrt(x_upw**2 + y_upw**2)
489 WRITE(*,*)
'Upwind umbrella point',x_upw,y_upw
490 WRITE(*,*)
'Upwind umbrella distance',d_upw_umb
492 WRITE(*,*)
'Radius increase', r_new_source/r_source
493 WRITE(*,*)
'Upwind spreading increase', d_upw_umb/d_upw_nbl
497 description =
'Radius old' 499 description =
'Radius new' 501 description =
'Radius increase' 503 description =
'Upwind distance old' 505 description =
'Upwind distance' 507 description =
'Upwind increase' 516 WRITE(*,*)
'Total time taken by the code is',t3-t1,
'seconds' 517 WRITE(*,*)
'Total elapsed real time is', dble( st3 - st1 ) / rate,
'seconds' 521 swu_file = trim(run_name)//
'.swu' 523 OPEN(swu_unit,file=swu_file,status=
'unknown',form=
'formatted')
527 WRITE(swu_unit,308) x_new_source , y_new_source , r_new_source , h_avg
529 307
FORMAT( 5x,
'x_new_source (m)', 14x,
'y_new_source (m)',14x,
'r_new_source (m)',14x,
'h_avg (m)')
531 308
FORMAT((7x,f14.4,16x,f14.4,16x,f14.4,9x,f14.4))
logical dakota_flag
Flag for dakota run (less files on output)
subroutine write_dakota(description, value)
Dakota outputs.
integer comp_cells_x
Number of control volumes x in the comp. domain.
real(wp) dt0
Initial time step.
integer, dimension(:), allocatable k_cent
integer comp_cells_y
Number of control volumes y in the comp. domain.
subroutine deallocate_solver_variables
Memory deallocation.
subroutine solve_umbrella
real(wp), dimension(:,:,:), allocatable q_mg_new
real(wp) t_output
time of the next output
integer n_vars
Number of conservative variables.
integer dak_unit
Dakota variables data unit.
real(wp), dimension(:), allocatable x_comp
Location of the centers (x) of the control volume of the domain.
logical hysplit_flag
Flag for hysplit run.
real(wp), dimension(:,:,:), allocatable qp
Physical variables ( )
subroutine init_grid
Finite volume grid initialization.
logical steady_flag
Flag to stop the umbrella solver when a steady upwind spreading is reached.
subroutine init_problem_param
Initialization of relaxation flags.
subroutine deallocate_grid
subroutine deallocate_multigrid
subroutine check_solve
Masking of cells to solve.
subroutine compute_cell_fract
subroutine timestep
Time-step computation.
subroutine qc_to_qp(qc, qp)
Conservative to physical variables.
integer, dimension(:), allocatable j_cent
real(wp) t_end
end time for the run
real(wp) dx
Control volumes size.
real(wp), dimension(:,:), allocatable upwind_dist
integer, parameter wp
working precision
real(wp), dimension(:,:), allocatable crosswind_dist
character(len=30) run_name
Name of the run (used for the output and backup files)
subroutine init_param
Initialization of the variables read from the input file.
real(wp) t_start
initial time for the run
real(wp), dimension(:,:,:), allocatable q
Conservative variables.
subroutine imex_rk_solver
Runge-Kutta integration.
logical, dimension(:,:), allocatable solve_mask
subroutine remap_solution
subroutine allocate_solver_variables
Memory allocation.
subroutine output_solution(time, steady_state)
Write the solution on the output unit.
real(wp), dimension(:), allocatable y_comp
Location of the centers (y) of the control volume of the domain.
real(wp) t_steady
end time when reached steady solution
real(wp) dy
Control volumes size.
subroutine allocate_multigrid