PLUME-MoM-TSM  1.0
VolcanicPlumeModel
constitutive_2d.f90
Go to the documentation of this file.
1 !********************************************************************************
3 !********************************************************************************
5 
6  USE variables, ONLY : wp
7  USE parameters_2d, ONLY : tolh
8  USE parameters_2d, ONLY : n_eqns , n_vars , c_d
9 
10  IMPLICIT none
11 
13  LOGICAL, ALLOCATABLE :: implicit_flag(:)
14 
15  REAL(wp) :: u_atm_umbl , v_atm_umbl
16  REAL(wp) :: n
17  REAL(wp) :: grav , drho_dz , rho_nbl
18 
19 CONTAINS
20 
21  !******************************************************************************
23  !
27  !******************************************************************************
28 
29  SUBROUTINE init_problem_param
30 
31  USE parameters_2d, ONLY : n_nh
32 
33  ALLOCATE( implicit_flag(n_eqns) )
34 
35  implicit_flag(1:n_eqns) = .false.
36  implicit_flag(2) = .true.
37  implicit_flag(3) = .true.
38 
39  n_nh = count( implicit_flag )
40 
41  RETURN
42 
43  END SUBROUTINE init_problem_param
44 
45  !******************************************************************************
47  !
58  !
61  !
63  !******************************************************************************
64 
65  SUBROUTINE r_phys_var(r_qj,r_h,r_u,r_v)
66 
67  USE parameters_2d, ONLY : eps_sing
68  IMPLICIT none
69 
70  REAL(wp), INTENT(IN) :: r_qj(n_vars)
71  REAL(wp), INTENT(OUT) :: r_h
72  REAL(wp), INTENT(OUT) :: r_u
73  REAL(wp), INTENT(OUT) :: r_v
74 
75  r_h = r_qj(1)
76 
77  ! velocity components
78  IF ( r_qj(1) .GT. eps_sing ) THEN
79 
80  r_u = r_qj(2) / r_qj(1)
81  r_v = r_qj(3) / r_qj(1)
82 
83  ELSE
84 
85  r_u = sqrt(2.0_wp) * r_qj(1) * r_qj(2) / sqrt( r_qj(1)**4 + eps_sing**4 )
86  r_v = sqrt(2.0_wp) * r_qj(1) * r_qj(3) / sqrt( r_qj(1)**4 + eps_sing**4 )
87 
88  END IF
89 
90  RETURN
91 
92  END SUBROUTINE r_phys_var
93 
94  !******************************************************************************
96  !
103  !
106  !
108  !******************************************************************************
109 
110  SUBROUTINE c_phys_var(c_qj,h,u,v)
112  USE complexify
113  USE parameters_2d, ONLY : eps_sing
114  IMPLICIT none
115 
116  COMPLEX(wp), INTENT(IN) :: c_qj(n_vars)
117  COMPLEX(wp), INTENT(OUT) :: h
118  COMPLEX(wp), INTENT(OUT) :: u
119  COMPLEX(wp), INTENT(OUT) :: v
120 
121  COMPLEX(wp) :: inv_cqj1
122 
123  IF ( REAL(c_qj(1)) .GT. eps_sing ) then
124 
125  inv_cqj1 = 1.0_wp / c_qj(1)
126 
127  ELSE
128 
129  inv_cqj1 = cmplx(0.0_wp,0.0_wp,wp)
130 
131  END IF
132 
133  h = c_qj(1)
134 
135  ! velocity components
136  IF ( REAL( c_qj(1) ) .GT. eps_sing ) then
137 
138  u = c_qj(2) * inv_cqj1
139  v = c_qj(3) * inv_cqj1
140 
141  ELSE
142 
143  u = sqrt(2.0_wp) * c_qj(1) * c_qj(2) / sqrt( c_qj(1)**4 + eps_sing**4 )
144  v = sqrt(2.0_wp) * c_qj(1) * c_qj(3) / sqrt( c_qj(1)**4 + eps_sing**4 )
145 
146  END IF
147 
148  RETURN
149 
150  END SUBROUTINE c_phys_var
151 
152  !******************************************************************************
154  !
159  !
162  !
164  !******************************************************************************
165 
166  SUBROUTINE mixt_var(qpj)
168  IMPLICIT none
169 
170  REAL(wp), INTENT(IN) :: qpj(n_vars+2)
171  REAL(wp) :: r_u
172  REAL(wp) :: r_v
173  REAL(wp) :: r_h
174 
175  r_h = qpj(1)
176 
177  IF ( qpj(1) .LE. 0.0_wp ) THEN
178 
179  r_u = 0.0_wp
180  r_v = 0.0_wp
181 
182  RETURN
183 
184  END IF
185 
186  r_u = qpj(n_vars+1)
187  r_v = qpj(n_vars+2)
188 
189  RETURN
190 
191  END SUBROUTINE mixt_var
192 
193  !******************************************************************************
195  !
208  !
210  !
213  !
214  !******************************************************************************
215 
216  SUBROUTINE qc_to_qp(qc,qp)
218  IMPLICIT none
219 
220  REAL(wp), INTENT(IN) :: qc(n_vars)
221  REAL(wp), INTENT(OUT) :: qp(n_vars+2)
222 
223  REAL(wp) :: r_h
224  REAL(wp) :: r_u
225  REAL(wp) :: r_v
226 
227  CALL r_phys_var(qc,r_h,r_u,r_v)
228 
229  qp(1) = r_h
230  qp(2) = r_h*r_u
231  qp(3) = r_h*r_v
232 
233  qp(n_vars+1) = r_u
234  qp(n_vars+2) = r_v
235 
236  RETURN
237 
238  END SUBROUTINE qc_to_qp
239 
240  !******************************************************************************
242  !
253  !
255  !
258  !
259  !******************************************************************************
260 
261  SUBROUTINE qp_to_qc(qp,qc)
263  IMPLICIT none
264 
265  REAL(wp), INTENT(IN) :: qp(n_vars+2)
266  REAL(wp), INTENT(OUT) :: qc(n_vars)
267 
268  REAL(wp) :: r_u
269  REAL(wp) :: r_v
270  REAL(wp) :: r_h
271  REAL(wp) :: r_hu
272  REAL(wp) :: r_hv
273 
274  r_h = qp(1)
275 
276  IF ( r_h .GT. 0.0_wp ) THEN
277 
278  r_hu = qp(2)
279  r_hv = qp(3)
280 
281  r_u = qp(n_vars+1)
282  r_v = qp(n_vars+2)
283 
284  ELSE
285 
286  r_hu = 0.0_wp
287  r_hv = 0.0_wp
288 
289  r_u = 0.0_wp
290  r_v = 0.0_wp
291 
292  qc(1:n_vars) = 0.0_wp
293  RETURN
294 
295  END IF
296 
297  qc(1) = r_h
298  qc(2) = r_hu
299  qc(3) = r_hv
300 
301  RETURN
302 
303  END SUBROUTINE qp_to_qc
304 
305  !******************************************************************************
307  !
316  !******************************************************************************
317 
318  SUBROUTINE qp_to_qp2(qpj,qp2j)
320  IMPLICIT none
321 
322  REAL(wp), INTENT(IN) :: qpj(n_vars)
323  REAL(wp), INTENT(OUT) :: qp2j(3)
324 
325  qp2j(1) = qpj(1)
326 
327  IF ( qpj(1) .LE. 0.0_wp ) THEN
328 
329  qp2j(2) = 0.0_wp
330  qp2j(3) = 0.0_wp
331 
332  ELSE
333 
334  qp2j(2) = qpj(2)/qpj(1)
335  qp2j(3) = qpj(3)/qpj(1)
336 
337  END IF
338 
339  RETURN
340 
341  END SUBROUTINE qp_to_qp2
342 
343  !******************************************************************************
345  !
354  !******************************************************************************
355 
356  SUBROUTINE eval_local_speeds_x(qpj,vel_min,vel_max)
358  IMPLICIT none
359 
360  REAL(wp), INTENT(IN) :: qpj(n_vars+2)
361 
362  REAL(wp), INTENT(OUT) :: vel_min(n_vars) , vel_max(n_vars)
363 
364  REAL(wp) :: r_h
365  REAL(wp) :: r_u
366 
367  r_h = qpj(1)
368  r_u = qpj(n_vars+1)
369 
370  vel_min(1:n_eqns) = r_u - 0.5_wp * n * r_h
371  vel_max(1:n_eqns) = r_u + 0.5_wp * n * r_h
372 
373  RETURN
374 
375  END SUBROUTINE eval_local_speeds_x
376 
377  !******************************************************************************
379  !
388  !******************************************************************************
389 
390  SUBROUTINE eval_local_speeds_y(qpj,vel_min,vel_max)
392  IMPLICIT none
393 
394  REAL(wp), INTENT(IN) :: qpj(n_vars+2)
395  REAL(wp), INTENT(OUT) :: vel_min(n_vars) , vel_max(n_vars)
396 
397  REAL(wp) :: r_h
398  REAL(wp) :: r_v
399 
400  r_h = qpj(1)
401  r_v = qpj(n_vars+2)
402 
403  vel_min(1:n_eqns) = r_v - 0.5_wp * n * r_h
404  vel_max(1:n_eqns) = r_v + 0.5_wp * n * r_h
405 
406  RETURN
407 
408  END SUBROUTINE eval_local_speeds_y
409 
410  !******************************************************************************
412  !
420  !
423  !
424  !******************************************************************************
425 
426  SUBROUTINE eval_fluxes(qcj,qpj,dir,flux)
428  IMPLICIT none
429 
430  REAL(wp), INTENT(IN) :: qcj(n_vars)
431  REAL(wp), INTENT(IN) :: qpj(n_vars+2)
432  INTEGER, INTENT(IN) :: dir
433 
434  REAL(wp), INTENT(OUT) :: flux(n_eqns)
435 
436  REAL(wp) :: r_h
437  REAL(wp) :: r_u
438  REAL(wp) :: r_v
439 
440  pos_thick:IF ( qcj(1) .GT. 0.0_wp ) THEN
441 
442  r_h = qpj(1)
443  r_u = qpj(n_vars+1)
444  r_v = qpj(n_vars+2)
445 
446  IF ( dir .EQ. 1 ) THEN
447 
448  ! Volume flux in x-direction: u * h
449  flux(1) = r_u * qcj(1)
450 
451  ! x-momentum flux in x-direction + hydrostatic pressure term
452  flux(2) = r_u * qcj(2) + n**2 * r_h**3 / 12.0_wp
453 
454  ! y-momentum flux in x-direction: u * (h * v)
455  flux(3) = r_u * qcj(3)
456 
457  ELSEIF ( dir .EQ. 2 ) THEN
458 
459  ! Volume flux in y-direction: v*h
460  flux(1) = r_v * qcj(1)
461 
462  ! y-momentum flux in y-direction: v * (h * v)
463  flux(2) = r_v * qcj(2)
464 
465  ! y-momentum flux in y-direction + hydrostatic pressure term
466  flux(3) = r_v * qcj(3) + n**2 * r_h**3 / 12.0_wp
467 
468  END IF
469 
470  ELSE
471 
472  flux(1:n_eqns) = 0.0_wp
473 
474  ENDIF pos_thick
475 
476  RETURN
477 
478  END SUBROUTINE eval_fluxes
479 
480  !******************************************************************************
482  !
492  !
495  !
496  !******************************************************************************
497 
498  SUBROUTINE eval_nonhyperbolic_terms( cell_fract_jk , dx_rel_jk , dy_rel_jk , &
499  c_qj , c_nh_term_impl , r_qj , r_nh_term_impl )
502 
503  USE complexify
504 
505  IMPLICIT NONE
506 
507  COMPLEX(wp), INTENT(IN), OPTIONAL :: c_qj(n_vars)
508  COMPLEX(wp), INTENT(OUT), OPTIONAL :: c_nh_term_impl(n_eqns)
509  REAL(wp), INTENT(IN), OPTIONAL :: r_qj(n_vars)
510  REAL(wp), INTENT(OUT), OPTIONAL :: r_nh_term_impl(n_eqns)
511 
512  REAL(wp), INTENT(IN) :: cell_fract_jk
513  REAL(wp), INTENT(IN) :: dx_rel_jk
514  REAL(wp), INTENT(IN) :: dy_rel_jk
515 
516  COMPLEX(wp) :: h
517  COMPLEX(wp) :: u
518  COMPLEX(wp) :: v
519 
520  COMPLEX(wp) :: qj(n_vars)
521  COMPLEX(wp) :: forces_term(n_eqns)
522 
523  COMPLEX(wp) :: mod_vel , delta_u , delta_v
524 
525  REAL(wp) :: pi_g
526 
527  REAL(wp) :: h_dot
528 
529  INTEGER :: i
530 
531  pi_g = 4.0_wp * atan(1.0_wp)
532 
533  IF ( present(c_qj) .AND. present(c_nh_term_impl) ) THEN
534 
535  qj = c_qj
536 
537  ELSEIF ( present(r_qj) .AND. present(r_nh_term_impl) ) THEN
538 
539  DO i = 1,n_vars
540 
541  qj(i) = cmplx( r_qj(i),0.0_wp,wp )
542 
543  END DO
544 
545  ELSE
546 
547  WRITE(*,*) 'Constitutive, eval_fluxes: problem with arguments'
548  stop
549 
550  END IF
551 
552  ! initialize and evaluate the forces terms
553  forces_term(1:n_eqns) = cmplx(0.0_wp,0.0_wp,wp)
554 
555  CALL c_phys_var(qj,h,u,v)
556 
557  delta_u = u - u_atm_umbl
558  delta_v = v - v_atm_umbl
559 
560  mod_vel = sqrt( delta_u**2 + delta_v**2 )
561 
562  forces_term(2) = forces_term(2) - c_d * delta_u * mod_vel
563 
564  forces_term(3) = forces_term(3) - c_d * delta_v * mod_vel
565 
566  h_dot = cell_fract_jk * vol_flux_source / (pi_g * r_source**2)
567 
568  forces_term(1) = h_dot
569 
570  forces_term(2) = forces_term(2) + ( u_source + dx_rel_jk * h_dot ) * h_dot
571 
572  forces_term(3) = forces_term(3) + ( v_source + dy_rel_jk * h_dot ) * h_dot
573 
574  IF ( present(c_qj) .AND. present(c_nh_term_impl) ) THEN
575 
576  c_nh_term_impl = forces_term
577 
578  ELSEIF ( present(r_qj) .AND. present(r_nh_term_impl) ) THEN
579 
580  r_nh_term_impl = REAL( forces_term )
581 
582  END IF
583 
584  RETURN
585 
586  END SUBROUTINE eval_nonhyperbolic_terms
587 
588  !******************************************************************************
590  !
600  !
603  !
604  !******************************************************************************
605 
606  SUBROUTINE eval_source_bdry( time, vect_x , vect_y , source_bdry )
609 
610  IMPLICIT NONE
611 
612  REAL(wp), INTENT(IN) :: time
613  REAL(wp), INTENT(IN) :: vect_x
614  REAL(wp), INTENT(IN) :: vect_y
615  REAL(wp), INTENT(OUT) :: source_bdry(n_vars)
616 
617  REAL(wp) :: t_rem
618  REAL(wp) :: t_coeff
619  REAL(wp) :: pi_g
620 
621  IF ( time .GE. time_param(4) ) THEN
622 
623  ! The exponents of t_coeff are such that Ri does not depend on t_coeff
624  source_bdry(1) = 0.0_wp
625  source_bdry(2) = 0.0_wp
626  source_bdry(3) = 0.0_wp
627  source_bdry(n_vars+1) = 0.0_wp
628  source_bdry(n_vars+2) = 0.0_wp
629 
630  RETURN
631 
632  END IF
633 
634  t_rem = mod( time , time_param(1) )
635 
636  pi_g = 4.0_wp * atan(1.0_wp)
637 
638  t_coeff = 0.0_wp
639 
640  IF ( time_param(3) .EQ. 0.0_wp ) THEN
641 
642  IF ( t_rem .LE. time_param(2) ) t_coeff = 1.0_wp
643 
644  ELSE
645 
646  IF ( t_rem .LT. time_param(3) ) THEN
647 
648  t_coeff = 0.5_wp * ( 1.0_wp - cos( pi_g * t_rem / time_param(3) ) )
649 
650  ELSEIF ( t_rem .LE. ( time_param(2) - time_param(3) ) ) THEN
651 
652  t_coeff = 1.0_wp
653 
654  ELSEIF ( t_rem .LE. time_param(2) ) THEN
655 
656  t_coeff = 0.5_wp * ( 1.0_wp + cos( pi_g * ( ( t_rem - time_param(2) ) &
657  / time_param(3) + 1.0_wp ) ) )
658 
659  END IF
660 
661  END IF
662 
663  ! The exponents of t_coeff are such that Ri does not depend on t_coeff
664  source_bdry(1) = t_coeff * h_source
665  source_bdry(2) = t_coeff**1.5_wp * h_source * vel_source * vect_x
666  source_bdry(3) = t_coeff**1.5_wp * h_source * vel_source * vect_y
667  source_bdry(n_vars+1) = t_coeff**0.5_wp * vel_source * vect_x
668  source_bdry(n_vars+2) = t_coeff**0.5_wp * vel_source * vect_y
669 
670  RETURN
671 
672  END SUBROUTINE eval_source_bdry
673 
674 END MODULE constitutive_2d
675 
676 
real(wp) h_source
subroutine eval_local_speeds_x(qpj, vel_min, vel_max)
Local Characteristic speeds x direction.
real(wp), parameter tolh
real(wp) r_source
Parameters.
subroutine qp_to_qp2(qpj, qp2j)
Additional Physical variables.
integer n_vars
Number of conservative variables.
subroutine eval_fluxes(qcj, qpj, dir, flux)
Hyperbolic Fluxes.
Constitutive equations.
logical, dimension(:), allocatable implicit_flag
flag used for size of implicit non linear-system
subroutine eval_source_bdry(time, vect_x, vect_y, source_bdry)
Internal boundary source fluxes.
subroutine eval_local_speeds_y(qpj, vel_min, vel_max)
Local Characteristic speeds y direction.
subroutine c_phys_var(c_qj, h, u, v)
Physical variables.
subroutine init_problem_param
Initialization of relaxation flags.
subroutine qc_to_qp(qc, qp)
Conservative to physical variables.
subroutine mixt_var(qpj)
Physical variables.
subroutine eval_nonhyperbolic_terms(cell_fract_jk, dx_rel_jk, dy_rel_jk, c_qj, c_nh_term_impl, r_qj, r_nh_term_impl)
Non-Hyperbolic terms.
integer, parameter wp
working precision
Definition: variables.f90:21
subroutine r_phys_var(r_qj, r_h, r_u, r_v)
Physical variables.
real(wp) vol_flux_source
real(wp) vel_source
integer n_eqns
Number of equations.
real(wp), dimension(4) time_param
real(wp) u_source
subroutine qp_to_qc(qp, qc)
Physical to conservative variables.
real(wp) v_source
real(wp) eps_sing
parameter for desingularization
Global variables.
Definition: variables.f90:10
integer n_nh
Number of non-hyperbolic terms.