PLUME-MoM-TSM  1.0
VolcanicPlumeModel
solver_2d.f90
Go to the documentation of this file.
1 !********************************************************************************
3 !
6 !
10 !
11 !********************************************************************************
12 MODULE solver_2d
13 
14  ! external variables
15 
16  USE constitutive_2d, ONLY : implicit_flag
17 
20 
21  USE geometry_2d, ONLY : source_cell
22 
23  USE variables, ONLY : wp , sp
24 
25  USE parameters_2d, ONLY : n_eqns , n_vars , n_nh
26  USE parameters_2d, ONLY : n_rk
27  USE parameters_2d, ONLY : verbose_level
28 
29  USE parameters_2d, ONLY : bcw , bce , bcs , bcn
30 
31  ! external procedures
32  USE geometry_2d, ONLY : limit
33 
34  USE omp_lib
35 
36  IMPLICIT none
37 
39  REAL(wp) :: t
40 
42  REAL(wp), ALLOCATABLE :: q(:,:,:)
44  REAL(wp), ALLOCATABLE :: q0(:,:,:)
46  REAL(wp), ALLOCATABLE :: q_fv(:,:,:)
47 
49  REAL(wp), ALLOCATABLE :: q_interfacel(:,:,:)
51  REAL(wp), ALLOCATABLE :: q_interfacer(:,:,:)
53  REAL(wp), ALLOCATABLE :: q_interfaceb(:,:,:)
55  REAL(wp), ALLOCATABLE :: q_interfacet(:,:,:)
56 
58  REAL(wp), ALLOCATABLE :: qp_interfacel(:,:,:)
60  REAL(wp), ALLOCATABLE :: qp_interfacer(:,:,:)
62  REAL(wp), ALLOCATABLE :: qp_interfaceb(:,:,:)
64  REAL(wp), ALLOCATABLE :: qp_interfacet(:,:,:)
65 
67  REAL(wp), ALLOCATABLE :: q_cellnw(:,:,:)
69  REAL(wp), ALLOCATABLE :: q_cellne(:,:,:)
71  REAL(wp), ALLOCATABLE :: q_cellsw(:,:,:)
73  REAL(wp), ALLOCATABLE :: q_cellse(:,:,:)
74 
76  REAL(wp), ALLOCATABLE :: qp_cellnw(:,:,:)
78  REAL(wp), ALLOCATABLE :: qp_cellne(:,:,:)
80  REAL(wp), ALLOCATABLE :: qp_cellsw(:,:,:)
82  REAL(wp), ALLOCATABLE :: qp_cellse(:,:,:)
83 
84 
86  REAL(wp), ALLOCATABLE :: q1max(:,:)
87 
89  REAL(wp), ALLOCATABLE :: a_interface_x_max(:,:,:)
91  REAL(wp), ALLOCATABLE :: a_interface_y_max(:,:,:)
92 
93 
95  REAL(wp), ALLOCATABLE :: a_interface_xneg(:,:,:)
97  REAL(wp), ALLOCATABLE :: a_interface_xpos(:,:,:)
99  REAL(wp), ALLOCATABLE :: a_interface_yneg(:,:,:)
101  REAL(wp), ALLOCATABLE :: a_interface_ypos(:,:,:)
103  REAL(wp), ALLOCATABLE :: h_interface_x(:,:,:)
105  REAL(wp), ALLOCATABLE :: h_interface_y(:,:,:)
107  REAL(wp), ALLOCATABLE :: qp(:,:,:)
108 
110  REAL(wp), ALLOCATABLE :: source_xy(:,:)
111 
112  LOGICAL, ALLOCATABLE :: solve_mask(:,:)
113  LOGICAL, ALLOCATABLE :: solve_mask_x(:,:)
114  LOGICAL, ALLOCATABLE :: solve_mask_y(:,:)
115 
116  INTEGER :: solve_cells
119 
121  REAL(wp) :: dt
122 
123  LOGICAL, ALLOCATABLE :: mask22(:,:) , mask21(:,:) , mask11(:,:) , mask12(:,:)
124 
125  INTEGER :: i_rk
126 
128  REAL(wp), ALLOCATABLE :: a_tilde_ij(:,:)
130  REAL(wp), ALLOCATABLE :: a_dirk_ij(:,:)
131 
133  REAL(wp), ALLOCATABLE :: omega_tilde(:)
134 
136  REAL(wp), ALLOCATABLE :: omega(:)
137 
139  REAL(wp), ALLOCATABLE :: a_tilde(:)
140 
142  REAL(wp), ALLOCATABLE :: a_dirk(:)
143 
145  REAL(wp) :: a_diag
146 
148  REAL(wp), ALLOCATABLE :: q_rk(:,:,:,:)
149 
151  REAL(wp), ALLOCATABLE :: qp_rk(:,:,:,:)
152 
154  REAL(wp), ALLOCATABLE :: divflux(:,:,:,:)
155 
157  REAL(wp), ALLOCATABLE :: nh(:,:,:,:)
158 
160  LOGICAL :: normalize_q
161 
163  LOGICAL :: normalize_f
164 
166  LOGICAL :: opt_search_nl
167 
169  REAL(wp), ALLOCATABLE :: residual_term(:,:,:)
170 
171  INTEGER, ALLOCATABLE :: j_cent(:)
172  INTEGER, ALLOCATABLE :: k_cent(:)
173 
174  INTEGER, ALLOCATABLE :: j_stag_x(:)
175  INTEGER, ALLOCATABLE :: k_stag_x(:)
176 
177  INTEGER, ALLOCATABLE :: j_stag_y(:)
178  INTEGER, ALLOCATABLE :: k_stag_y(:)
179 
180  REAL(wp), ALLOCATABLE :: q_mg_old(:,:,:)
181  REAL(wp), ALLOCATABLE :: q_mg_new(:,:,:)
182 
183 
184 CONTAINS
185 
186  !******************************************************************************
188  !
191  !
195  !
196  !******************************************************************************
197 
198  SUBROUTINE allocate_solver_variables
200  IMPLICIT NONE
201 
202  REAL(wp) :: gamma , delta
203 
204  INTEGER :: i,j
205 
206  ALLOCATE( q( n_vars , comp_cells_x , comp_cells_y ) , q0( n_vars , &
207  comp_cells_x , comp_cells_y ) )
208 
209  ALLOCATE( qp( n_vars+2 , comp_cells_x , comp_cells_y ) )
210 
211  q(1:n_vars,1:comp_cells_x,1:comp_cells_y) = 0.0_wp
212  qp(1:n_vars+2,1:comp_cells_x,1:comp_cells_y) = 0.0_wp
213 
214  ALLOCATE( q1max( comp_cells_x , comp_cells_y ) )
215 
216  ALLOCATE( q_fv( n_vars , comp_cells_x , comp_cells_y ) )
217 
218  ALLOCATE( q_interfacel( n_vars , comp_interfaces_x, comp_cells_y ) )
219  ALLOCATE( q_interfacer( n_vars , comp_interfaces_x, comp_cells_y ) )
220  ALLOCATE( a_interface_xneg( n_eqns , comp_interfaces_x, comp_cells_y ) )
221  ALLOCATE( a_interface_xpos( n_eqns , comp_interfaces_x, comp_cells_y ) )
222 
223  a_interface_xneg = 0.0_wp
224  a_interface_xpos = 0.0_wp
225 
226  ALLOCATE( h_interface_x( n_eqns , comp_interfaces_x, comp_cells_y ) )
227  ALLOCATE( h_interface_y( n_eqns , comp_cells_x, comp_interfaces_y ) )
228 
229 
230  ALLOCATE( q_interfaceb( n_vars , comp_cells_x, comp_interfaces_y ) )
231  ALLOCATE( q_interfacet( n_vars , comp_cells_x, comp_interfaces_y ) )
232  ALLOCATE( a_interface_yneg( n_eqns , comp_cells_x, comp_interfaces_y ) )
233  ALLOCATE( a_interface_ypos( n_eqns , comp_cells_x, comp_interfaces_y ) )
234 
235  a_interface_yneg = 0.0_wp
236  a_interface_ypos = 0.0_wp
237 
238 
239  ALLOCATE( qp_interfacel( n_vars+2 , comp_interfaces_x, comp_cells_y ) )
240  ALLOCATE( qp_interfacer( n_vars+2 , comp_interfaces_x, comp_cells_y ) )
241  ALLOCATE( qp_interfaceb( n_vars+2 , comp_cells_x, comp_interfaces_y ) )
242  ALLOCATE( qp_interfacet( n_vars+2 , comp_cells_x, comp_interfaces_y ) )
243 
244 
245  ALLOCATE( q_cellnw( n_vars , comp_cells_x , comp_cells_y ) )
246  ALLOCATE( q_cellne( n_vars , comp_cells_x , comp_cells_y ) )
247  ALLOCATE( q_cellsw( n_vars , comp_cells_x , comp_cells_y ) )
248  ALLOCATE( q_cellse( n_vars , comp_cells_x , comp_cells_y ) )
249 
250  ALLOCATE( qp_cellnw( n_vars+2 , comp_cells_x , comp_cells_y ) )
251  ALLOCATE( qp_cellne( n_vars+2 , comp_cells_x , comp_cells_y ) )
252  ALLOCATE( qp_cellsw( n_vars+2 , comp_cells_x , comp_cells_y ) )
253  ALLOCATE( qp_cellse( n_vars+2 , comp_cells_x , comp_cells_y ) )
254 
255 
256  ALLOCATE ( a_interface_x_max(n_eqns,comp_interfaces_x,comp_cells_y) )
257  ALLOCATE ( a_interface_y_max(n_eqns,comp_cells_x,comp_interfaces_y) )
258 
259  ALLOCATE( solve_mask( comp_cells_x , comp_cells_y ) )
260 
261  solve_mask(1,1:comp_cells_y) = .true.
262  solve_mask(comp_cells_x,1:comp_cells_y) = .true.
263  solve_mask(1:comp_cells_x,1) = .true.
264  solve_mask(1:comp_cells_x,comp_cells_y) = .true.
265 
266 
267  ALLOCATE( solve_mask_x( comp_interfaces_x , comp_cells_y ) )
268  ALLOCATE( solve_mask_y( comp_cells_x , comp_interfaces_y ) )
269 
270  ALLOCATE( source_xy( comp_cells_x , comp_cells_y ) )
271 
272 
273  ALLOCATE( a_tilde_ij(n_rk,n_rk) )
274  ALLOCATE( a_dirk_ij(n_rk,n_rk) )
275  ALLOCATE( omega_tilde(n_rk) )
276  ALLOCATE( omega(n_rk) )
277 
278 
279  ! Allocate the logical arrays defining the implicit parts of the system
280  ALLOCATE( mask22(n_eqns,n_eqns) )
281  ALLOCATE( mask21(n_eqns,n_eqns) )
282  ALLOCATE( mask11(n_eqns,n_eqns) )
283  ALLOCATE( mask12(n_eqns,n_eqns) )
284 
285  ! Initialize the logical arrays with all false (everything is implicit)
286  mask11(1:n_eqns,1:n_eqns) = .false.
287  mask12(1:n_eqns,1:n_eqns) = .false.
288  mask22(1:n_eqns,1:n_eqns) = .false.
289  mask21(1:n_eqns,1:n_eqns) = .false.
290 
291  ! Set to .TRUE. the elements not corresponding to equations and variables to
292  ! be solved implicitly
293  DO i = 1,n_eqns
294 
295  DO j = 1,n_eqns
296 
297  IF ( .NOT.implicit_flag(i) .AND. .NOT.implicit_flag(j) ) &
298  mask11(j,i) = .true.
299  IF ( implicit_flag(i) .AND. .NOT.implicit_flag(j) ) &
300  mask12(j,i) = .true.
301  IF ( implicit_flag(i) .AND. implicit_flag(j) ) &
302  mask22(j,i) = .true.
303  IF ( .NOT.implicit_flag(i) .AND. implicit_flag(j) ) &
304  mask21(j,i) = .true.
305 
306  END DO
307 
308  END DO
309 
310  ! Initialize the coefficients for the IMEX Runge-Kutta scheme
311  ! Please note that with respect to the schemes described in Pareschi & Russo
312  ! (2000) we do not have the coefficient vectors c_tilde and c, because the
313  ! explicit and implicit terms do not depend explicitly on time.
314 
315  ! Explicit part coefficients (a_tilde_ij=0 for j>=i)
316  a_tilde_ij = 0.0_wp
317 
318  ! Weight coefficients of the explicit part in the final assemblage
319  omega_tilde = 0.0_wp
320 
321  ! Implicit part coefficients (a_dirk_ij=0 for j>i)
322  a_dirk_ij = 0.0_wp
323 
324  ! Weight coefficients of the explicit part in the final assemblage
325  omega = 0.0_wp
326 
327  gamma = 1.0_wp - 1.0_wp / sqrt(2.0_wp)
328  delta = 1.0_wp - 1.0_wp / ( 2.0_wp * gamma )
329 
330  IF ( n_rk .EQ. 1 ) THEN
331 
332  a_tilde_ij(1,1) = 1.0_wp
333 
334  omega_tilde(1) = 1.0_wp
335 
336  a_dirk_ij(1,1) = 0.0_wp
337 
338  omega(1) = 0.0_wp
339 
340  ELSEIF ( n_rk .EQ. 2 ) THEN
341 
342  a_tilde_ij(2,1) = 1.0_wp
343 
344  omega_tilde(1) = 1.0_wp
345  omega_tilde(2) = 0.0_wp
346 
347  a_dirk_ij(2,2) = 1.0_wp
348 
349  omega(1) = 0.0_wp
350  omega(2) = 1.0_wp
351 
352  ELSEIF ( n_rk .EQ. 3 ) THEN
353 
354  ! Tableau for the IMEX-SSP(3,3,2) Stiffly Accurate Scheme
355  ! from Pareschi & Russo (2005), Table IV
356 
357  a_tilde_ij(2,1) = 0.5_wp
358  a_tilde_ij(3,1) = 0.5_wp
359  a_tilde_ij(3,2) = 0.5_wp
360 
361  omega_tilde(1) = 1.0_wp / 3.0_wp
362  omega_tilde(2) = 1.0_wp / 3.0_wp
363  omega_tilde(3) = 1.0_wp / 3.0_wp
364 
365  a_dirk_ij(1,1) = 0.25_wp
366  a_dirk_ij(2,2) = 0.25_wp
367  a_dirk_ij(3,1) = 1.0_wp / 3.0_wp
368  a_dirk_ij(3,2) = 1.0_wp / 3.0_wp
369  a_dirk_ij(3,3) = 1.0_wp / 3.0_wp
370 
371  omega(1) = 1.0_wp / 3.0_wp
372  omega(2) = 1.0_wp / 3.0_wp
373  omega(3) = 1.0_wp / 3.0_wp
374 
375  ELSEIF ( n_rk .EQ. 4 ) THEN
376 
377  ! LRR(3,2,2) from Table 3 in Pareschi & Russo (2000)
378 
379  a_tilde_ij(2,1) = 0.5_wp
380  a_tilde_ij(3,1) = 1.0_wp / 3.0_wp
381  a_tilde_ij(4,2) = 1.0_wp
382 
383  omega_tilde(1) = 0.0_wp
384  omega_tilde(2) = 1.0_wp
385  omega_tilde(3) = 0.0_wp
386  omega_tilde(4) = 0.0_wp
387 
388  a_dirk_ij(2,2) = 0.5_wp
389  a_dirk_ij(3,3) = 1.0_wp / 3.0_wp
390  a_dirk_ij(4,3) = 0.75_wp
391  a_dirk_ij(4,4) = 0.25_wp
392 
393  omega(1) = 0.0_wp
394  omega(2) = 0.0_wp
395  omega(3) = 0.75_wp
396  omega(4) = 0.25_wp
397 
398  END IF
399 
400  ALLOCATE( a_tilde(n_rk) )
401  ALLOCATE( a_dirk(n_rk) )
402 
403  ALLOCATE( q_rk( n_vars , comp_cells_x , comp_cells_y , n_rk ) )
404  ALLOCATE( qp_rk( n_vars+2 , comp_cells_x , comp_cells_y , n_rk ) )
405  ALLOCATE( divflux( n_eqns , comp_cells_x , comp_cells_y , n_rk ) )
406  ALLOCATE( nh( n_eqns , comp_cells_x , comp_cells_y , n_rk ) )
407 
408  ALLOCATE( residual_term( n_vars , comp_cells_x , comp_cells_y ) )
409 
410  comp_cells_xy = comp_cells_x * comp_cells_y
411 
412  ALLOCATE( j_cent( comp_cells_xy ) )
413  ALLOCATE( k_cent( comp_cells_xy ) )
414 
415  ALLOCATE( j_stag_x( comp_interfaces_x * comp_cells_y ) )
416  ALLOCATE( k_stag_x( comp_interfaces_x * comp_cells_y ) )
417 
418  ALLOCATE( j_stag_y( comp_cells_x * comp_interfaces_y ) )
419  ALLOCATE( k_stag_y( comp_cells_x * comp_interfaces_y ) )
420 
421  RETURN
422 
423  END SUBROUTINE allocate_solver_variables
424 
425  !******************************************************************************
427  !
430  !
434  !
435  !******************************************************************************
436 
437  SUBROUTINE deallocate_solver_variables
439  DEALLOCATE( q , q0 )
440 
441  DEALLOCATE( qp )
442 
443  DEALLOCATE( q1max )
444 
445  DEALLOCATE( q_fv )
446 
447  DEALLOCATE( q_interfacel )
448  DEALLOCATE( q_interfacer )
449  DEALLOCATE( a_interface_xneg )
450  DEALLOCATE( a_interface_xpos )
451 
452  DEALLOCATE( h_interface_x )
453  DEALLOCATE( h_interface_y )
454 
455 
456  DEALLOCATE( q_interfaceb )
457  DEALLOCATE( q_interfacet )
458  DEALLOCATE( a_interface_yneg )
459  DEALLOCATE( a_interface_ypos )
460 
461  DEALLOCATE( qp_interfacel )
462  DEALLOCATE( qp_interfacer )
463  DEALLOCATE( qp_interfaceb )
464  DEALLOCATE( qp_interfacet )
465 
466 
467  DEALLOCATE( q_cellnw )
468  DEALLOCATE( q_cellne )
469  DEALLOCATE( q_cellsw )
470  DEALLOCATE( q_cellse )
471 
472  DEALLOCATE( qp_cellnw )
473  DEALLOCATE( qp_cellne )
474  DEALLOCATE( qp_cellsw )
475  DEALLOCATE( qp_cellse )
476 
477 
478  DEALLOCATE( a_interface_x_max )
479  DEALLOCATE( a_interface_y_max )
480 
481  DEALLOCATE( solve_mask )
482 
483  DEALLOCATE( solve_mask_x )
484  DEALLOCATE( solve_mask_y )
485 
486  DEALLOCATE( source_xy )
487 
488 
489  DEALLOCATE( a_tilde_ij )
490  DEALLOCATE( a_dirk_ij )
491  DEALLOCATE( omega_tilde )
492  DEALLOCATE( omega )
493 
494 
495  ! Allocate the logical arrays defining the implicit parts of the system
496  DEALLOCATE( mask22 )
497  DEALLOCATE( mask21 )
498  DEALLOCATE( mask11 )
499  DEALLOCATE( mask12 )
500 
501 
502  DEALLOCATE( a_tilde )
503  DEALLOCATE( a_dirk )
504 
505  DEALLOCATE( q_rk )
506  DEALLOCATE( qp_rk )
507  DEALLOCATE( divflux )
508  DEALLOCATE( nh )
509  DEALLOCATE( residual_term )
510 
511  DEALLOCATE( j_cent )
512  DEALLOCATE( k_cent )
513 
514  DEALLOCATE( j_stag_x )
515  DEALLOCATE( k_stag_x )
516 
517  DEALLOCATE( j_stag_y )
518  DEALLOCATE( k_stag_y )
519 
520 
521  RETURN
522 
523  END SUBROUTINE deallocate_solver_variables
524 
525 
526  SUBROUTINE allocate_multigrid
528  ALLOCATE( q_mg_old(n_vars , comp_cells_x , comp_cells_y) )
529  ALLOCATE( q_mg_new(n_vars , 2*comp_cells_x , 2*comp_cells_y) )
530 
531  END SUBROUTINE allocate_multigrid
532 
533  SUBROUTINE deallocate_multigrid
535  DEALLOCATE( q_mg_old )
536  DEALLOCATE( q_mg_new )
537 
538  END SUBROUTINE deallocate_multigrid
539 
540  SUBROUTINE remap_solution
542  USE geometry_2d, ONLY : x0 , y0 , cell_size
543  USE geometry_2d, ONLY : x_stag , y_stag
544 
545  USE geometry_2d, ONLY : regrid_scalar
546 
547  IMPLICIT NONE
548 
549  INTEGER :: i ,j ,k
550 
551  REAL(wp) :: xl , xr
552  REAL(wp) :: yl , yr
553 
554  WRITE(*,*) 'INT(q(1,:,:)=',sum(q(1,:,:))*cell_size*cell_size
555 
556  DO k = 1,2*comp_cells_y
557 
558  yl = y0 + (k-1)*0.5_wp*cell_size
559  yr = y0 + (k)*0.5_wp*cell_size
560 
561  DO j = 1,2*comp_cells_x
562 
563  xl = x0 + (j-1)*0.5_wp*cell_size
564  xr = x0 + (j)*0.5_wp*cell_size
565 
566  DO i=1,n_vars
567 
568  CALL regrid_scalar(x_stag, y_stag, q(i,:,:), xl, xr , yl, yr, q_mg_new(i,j,k) )
569 
570  END DO
571 
572  END DO
573 
574  END DO
575 
576  WRITE(*,*) 'size q_mg_new',SIZE(q_mg_new)
577  WRITE(*,*) 'SUM(q_mg_new(1,:,:)=',sum(q_mg_new(1,:,:))*0.25_wp*cell_size*cell_size
578  READ(*,*)
579 
580  RETURN
581 
582  END SUBROUTINE remap_solution
583 
584  !******************************************************************************
586  !
590  !
594  !
595  !******************************************************************************
596 
597  SUBROUTINE check_solve
599  IMPLICIT NONE
600 
601  INTEGER :: i,j,k
602 
603  !$OMP PARALLEL
604 
605  !$OMP WORKSHARE
606  WHERE ( q(1,2:comp_cells_x-1,2:comp_cells_y-1) .GT. 0.0_wp ) &
607  solve_mask(2:comp_cells_x,2:comp_cells_y) = .true.
608 
609  !$OMP END WORKSHARE
610 
611  !$OMP SINGLE
612 
613  DO i = 1,n_rk
614 
615  ! solution domain is extended to neighbours of positive-mass cells
616  solve_mask(2:comp_cells_x-1,2:comp_cells_y-1) = &
617  solve_mask(2:comp_cells_x-1,2:comp_cells_y-1) .OR. &
618  solve_mask(1:comp_cells_x-2,2:comp_cells_y-1) .OR. &
619  solve_mask(3:comp_cells_x,2:comp_cells_y-1) .OR. &
620  solve_mask(2:comp_cells_x-1,1:comp_cells_y-2) .OR. &
621  solve_mask(2:comp_cells_x-1,3:comp_cells_y)
622 
623  END DO
624 
625  !$OMP END SINGLE
626 
627  !$OMP WORKSHARE
628 
629  solve_mask_x(1:comp_interfaces_x,1:comp_cells_y) = .false.
630  solve_mask_y(1:comp_cells_x,1:comp_interfaces_y) = .false.
631 
632  !$OMP END WORKSHARE
633 
634  !$OMP END PARALLEL
635 
636  !----- check for cells where computation is needed
637  i = 0
638 
639  DO k = 1,comp_cells_y
640 
641  DO j = 1,comp_cells_x
642 
643  IF ( solve_mask(j,k) ) THEN
644 
645  i = i+1
646  j_cent(i) = j
647  k_cent(i) = k
648 
649  solve_mask_x(j,k) = .true.
650  solve_mask_x(j+1,k) = .true.
651  solve_mask_y(j,k) = .true.
652  solve_mask_y(j,k+1) = .true.
653 
654  END IF
655 
656  END DO
657 
658  END DO
659 
660  solve_cells = i
661 
662  !----- check for y-interfaces where computation is needed
663  i = 0
664 
665  DO k = 1,comp_cells_y
666 
667  DO j = 1,comp_interfaces_x
668 
669  IF ( solve_mask_x(j,k) ) THEN
670 
671  i = i+1
672  j_stag_x(i) = j
673  k_stag_x(i) = k
674 
675  END IF
676 
677  END DO
678 
679  END DO
680 
682 
683  !----- check for y-interfaces where computation is needed
684 
685  i = 0
686 
687  DO k = 1,comp_interfaces_y
688 
689  DO j = 1,comp_cells_x
690 
691  IF ( solve_mask_y(j,k) ) THEN
692 
693  i = i+1
694  j_stag_y(i) = j
695  k_stag_y(i) = k
696 
697  END IF
698 
699  END DO
700 
701  END DO
702 
704 
705  RETURN
706 
707  WRITE(*,*) solve_mask_y
708  READ(*,*)
709 
710 
711  END SUBROUTINE check_solve
712 
713  !*****************************************************************************
715  !
719  !
723  !
724  !*****************************************************************************
725 
726  SUBROUTINE timestep
728  ! External variables
729  USE geometry_2d, ONLY : dx,dy
730  USE parameters_2d, ONLY : max_dt , cfl
731 
732  USE constitutive_2d, ONLY : qc_to_qp
733 
734  IMPLICIT none
735 
736  REAL(wp) :: dt_cfl
737 
738  REAL(wp) :: dt_interface_x, dt_interface_y
739 
740  INTEGER :: i,j,k,l
741 
742  REAL(wp) :: max_a
743 
744  dt = max_dt
745 
746  IF ( cfl .NE. -1.0_wp ) THEN
747 
748  !$OMP PARALLEL DO private(j,k)
749 
750  DO l = 1,solve_cells
751 
752  j = j_cent(l)
753  k = k_cent(l)
754 
755  IF ( q(1,j,k) .GT. 0.0_wp ) THEN
756 
757  CALL qc_to_qp( q(1:n_vars,j,k) , qp(1:n_vars+2,j,k) )
758 
759  ELSE
760 
761  qp(1:n_vars+2,j,k) = 0.0_wp
762 
763  END IF
764 
765  END DO
766 
767  !$OMP END PARALLEL DO
768 
769  ! Compute the physical and conservative variables at the interfaces
770  CALL reconstruction( q , qp )
771 
772  ! Compute the max/min eigenvalues at the interfaces
773  CALL eval_speeds
774 
775 
776  !$OMP PARALLEL DO private(j,k)
777  DO l = 1,solve_interfaces_x
778 
779  j = j_stag_x(l)
780  k = k_stag_x(l)
781 
782  DO i=1,n_vars
783 
784  a_interface_x_max(i,j,k) = &
785  max( a_interface_xpos(i,j,k) , -a_interface_xneg(i,j,k) )
786 
787  END DO
788 
789  END DO
790  !$OMP END PARALLEL DO
791 
792 
793  !$OMP PARALLEL DO private(j,k)
794  DO l = 1,solve_interfaces_y
795 
796  j = j_stag_y(l)
797  k = k_stag_y(l)
798 
799  DO i=1,n_vars
800 
801  a_interface_y_max(i,j,k) = &
802  max( a_interface_ypos(i,j,k) , -a_interface_yneg(i,j,k) )
803 
804 
805  END DO
806 
807  END DO
808  !$OMP END PARALLEL DO
809 
810  DO l = 1,solve_cells
811 
812  j = j_cent(l)
813  k = k_cent(l)
814 
815  max_a = max( maxval(a_interface_x_max(:,j,k)) , &
816  maxval(a_interface_x_max(:,j+1,k)) )
817 
818  IF ( max_a .GT. 0.0_wp ) THEN
819 
820  dt_interface_x = cfl * dx / max_a
821 
822  ELSE
823 
824  dt_interface_x = dt
825 
826  END IF
827 
828  max_a = max( maxval(a_interface_y_max(:,j,k)) , &
829  maxval(a_interface_y_max(:,j,k+1)) )
830 
831  IF ( max_a .GT. 0.0_wp ) THEN
832 
833  dt_interface_y = cfl * dy / max_a
834 
835  ELSE
836 
837  dt_interface_y = dt
838 
839  END IF
840 
841  dt_cfl = min( dt_interface_x , dt_interface_y )
842 
843  dt = min(dt,dt_cfl)
844 
845  END DO
846 
847  END IF
848 
849  RETURN
850 
851  END SUBROUTINE timestep
852 
853  !******************************************************************************
855  !
860  !
864  !
865  !******************************************************************************
866 
867  SUBROUTINE imex_rk_solver
870 
871  USE constitutive_2d, ONLY : qc_to_qp
872 
873  USE geometry_2d, ONLY : cell_fract , dx_rel , dy_rel
874 
875  IMPLICIT NONE
876 
877  REAL(wp) :: q_si(n_vars)
878  REAL(wp) :: q_guess(n_vars)
879  INTEGER :: j,k,l
880  REAL(wp) :: Rj_not_impl(n_eqns)
881 
882  IF ( verbose_level .GE. 2 ) WRITE(*,*) 'solver, imex_RK_solver: beginning'
883 
884  !$OMP PARALLEL DO private(j,k,q_guess,q_si,Rj_not_impl)
885  init_cells_loop:DO l = 1,solve_cells
886 
887  j = j_cent(l)
888  k = k_cent(l)
889 
890  ! Initialization of the solution guess
891  q0( 1:n_vars , j , k ) = &
892  q( 1:n_vars , j , k )
893 
894  ! Initialization of the variables for the Runge-Kutta scheme
895  q_rk( 1:n_vars , j , k , 1:n_rk ) = 0.0_wp
896  qp_rk( 1:n_vars+2 , j , k , 1:n_rk ) = 0.0_wp
897  divflux(1:n_eqns , j , k , 1:n_rk ) = 0.0_wp
898  nh( 1:n_eqns, j , k , 1:n_rk ) = 0.0_wp
899 
900  END DO init_cells_loop
901  !$OMP END PARALLEL DO
902 
903  runge_kutta:DO i_rk = 1,n_rk
904 
905  IF ( verbose_level .GE. 2 ) WRITE(*,*) 'solver, imex_RK_solver: i_RK',i_rk
906 
907  ! define the explicits coefficients for the i-th step of the Runge-Kutta
908  a_tilde = 0.0_wp
909  a_dirk = 0.0_wp
910 
911  ! in the first step of the RK scheme all the coefficients remain to 0
912  a_tilde(1:i_rk-1) = a_tilde_ij(i_rk,1:i_rk-1)
913  a_dirk(1:i_rk-1) = a_dirk_ij(i_rk,1:i_rk-1)
914 
915  ! define the implicit coefficient for the i-th step of the Runge-Kutta
917 
918  !$OMP PARALLEL
919  !$OMP DO private(j,k,q_guess,q_si,Rj_not_impl)
920 
921  solve_cells_loop:DO l = 1,solve_cells
922 
923  j = j_cent(l)
924  k = k_cent(l)
925 
926  IF ( verbose_level .GE. 2 ) THEN
927 
928  WRITE(*,*) 'solver, imex_RK_solver: j',j,k
929 
930  END IF
931 
932  ! initialize the RK step
933  IF ( i_rk .EQ. 1 ) THEN
934 
935  ! solution from the previous time step
936  q_guess(1:n_vars) = q0( 1:n_vars , j , k)
937 
938  ELSE
939 
940  ! solution from the previous RK step
941  !q_guess(1:n_vars) = q_rk( 1:n_vars , j , k , MAX(1,i_RK-1))
942 
943  END IF
944 
945  ! New solution at the i_RK step without the implicit and
946  ! semi-implicit term
947  q_fv( 1:n_vars , j , k ) = q0( 1:n_vars , j , k ) &
948  - dt * (matmul( divflux(1:n_eqns,j,k,1:i_rk) , a_tilde(1:i_rk) ) &
949  - matmul( nh(1:n_eqns,j,k,1:i_rk) , a_dirk(1:i_rk) ) )
950 
951  IF ( verbose_level .GE. 2 ) THEN
952 
953  WRITE(*,*) 'q_guess',q_guess
954  IF ( q_guess(1) .GT. 0.0_wp ) THEN
955 
956  CALL qc_to_qp( q_guess , qp(1:n_vars+2,j,k) )
957  WRITE(*,*) 'q_guess: qp',qp(1:n_vars+2,j,k)
958 
959  END IF
960 
961  END IF
962 
963  adiag_pos:IF ( a_diag .NE. 0.0_wp ) THEN
964 
965  pos_thick:IF ( ( q_fv(1,j,k) .GT. 0.0_wp ) .OR. ( cell_fract(j,k) .GT. 0.0_wp ) ) THEN
966  !pos_thick:IF ( q_fv(1,j,k) .GT. 0.0_wp ) THEN
967 
968  ! Initialize the guess for the NR solver
969  q_guess(1:n_vars) = q_fv(1:n_vars,j,k)
970 
971  rj_not_impl = matmul( divflux(1:n_eqns,j,k,1:i_rk-1) , a_tilde(1:i_rk-1) ) &
972  - matmul( nh(1:n_eqns,j,k,1:i_rk-1) , a_dirk(1:i_rk-1) )
973 
974  ! Solve the implicit system to find the solution at the
975  ! i_RK step of the IMEX RK procedure
976  CALL solve_rk_step( cell_fract(j,k) , dx_rel(j,k) , dy_rel(j,k),&
977  q_guess(1:n_vars) , q0(1:n_vars,j,k ) , &
978  a_tilde , a_dirk , a_diag , rj_not_impl , &
979  divflux( 1:n_eqns , j , k , 1:n_rk ) , &
980  nh( 1:n_eqns , j , k , 1:n_rk ) )
981 
982  IF ( comp_cells_y .EQ. 1 ) THEN
983 
984  q_guess(3) = 0.0_wp
985 
986  END IF
987 
988  IF ( comp_cells_x .EQ. 1 ) THEN
989 
990  q_guess(2) = 0.0_wp
991 
992  END IF
993 
994  ! Eval and store the implicit term at the i_RK step
995  CALL eval_nonhyperbolic_terms( cell_fract(j,k), dx_rel(j,k) , &
996  dy_rel(j,k) , r_qj = q_guess , &
997  r_nh_term_impl = nh(1:n_eqns,j,k,i_rk) )
998 
999  ELSE
1000 
1001  ! If h=0 nothing has to be changed
1002  q_guess(1:n_vars) = q_fv( 1:n_vars , j , k )
1003  nh(1:n_eqns,j,k,i_rk) = 0.0_wp
1004 
1005  END IF pos_thick
1006 
1007  END IF adiag_pos
1008 
1009  IF ( a_diag .NE. 0.0_wp ) THEN
1010 
1011  ! Update the implicit term with correction on the new velocity
1012  nh(1:n_vars,j,k,i_rk) = ( q_guess(1:n_vars) - q_fv(1:n_vars,j,k) ) &
1013  / ( dt*a_diag )
1014 
1015  END IF
1016 
1017  ! Store the solution at the end of the i_RK step
1018  q_rk( 1:n_vars , j , k , i_rk ) = q_guess
1019 
1020  IF ( verbose_level .GE. 2 ) THEN
1021 
1022  WRITE(*,*) 'imex_RK_solver: qc',q_guess
1023 
1024  IF ( q_guess(1) .GT. 0.0_wp ) THEN
1025 
1026  CALL qc_to_qp( q_guess , qp(1:n_vars+2,j,k) )
1027  WRITE(*,*) 'imex_RK_solver: qp',qp(1:n_vars+2,j,k)
1028 
1029  END IF
1030 
1031  READ(*,*)
1032 
1033  END IF
1034 
1035  IF ( omega_tilde(i_rk) .GT. 0.0_wp ) THEN
1036 
1037  IF ( q_rk(1,j,k,i_rk) .GT. 0.0_wp ) THEN
1038 
1039  CALL qc_to_qp( q_rk(1:n_vars,j,k,i_rk) , &
1040  qp_rk(1:n_vars+2,j,k,i_rk) )
1041 
1042  ELSE
1043 
1044  qp_rk(1:n_vars+2,j,k,i_rk) = 0.0_wp
1045 
1046  END IF
1047 
1048  END IF
1049 
1050  END DO solve_cells_loop
1051 
1052  !$OMP END DO
1053 
1054  !$OMP END PARALLEL
1055 
1056  IF ( omega_tilde(i_rk) .GT. 0.0_wp ) THEN
1057 
1058  ! Eval and store the explicit hyperbolic (fluxes) terms
1059  CALL eval_hyperbolic_terms( &
1060  q_rk(1:n_vars,1:comp_cells_x,1:comp_cells_y,i_rk) , &
1061  qp_rk(1:n_vars+2,1:comp_cells_x,1:comp_cells_y,i_rk) , &
1062  divflux(1:n_eqns,1:comp_cells_x,1:comp_cells_y,i_rk) )
1063 
1064  END IF
1065 
1066  END DO runge_kutta
1067 
1068  !$OMP PARALLEL DO private(j,k)
1069 
1070  assemble_sol:DO l = 1,solve_cells
1071 
1072  j = j_cent(l)
1073  k = k_cent(l)
1074 
1075  residual_term(1:n_vars,j,k) = matmul( divflux(1:n_eqns,j,k,1:n_rk) , &
1076  omega_tilde ) - matmul( nh(1:n_eqns,j,k,1:n_rk) , omega )
1077 
1078  IF ( verbose_level .GE. 1 ) THEN
1079 
1080  WRITE(*,*) 'cell jk =',j,k
1081  WRITE(*,*) 'before imex_RK_solver: qc',q0(1:n_vars,j,k)
1082  IF ( q0(1,j,k) .GT. 0.0_wp ) THEN
1083 
1084  CALL qc_to_qp(q0(1:n_vars,j,k) , qp(1:n_vars+2,j,k))
1085  WRITE(*,*) 'before imex_RK_solver: qp',qp(1:n_vars+2,j,k)
1086 
1087  END IF
1088 
1089  END IF
1090 
1091  IF ( ( sum(abs( omega_tilde(:)-a_tilde_ij(n_rk,:))) .EQ. 0.0_wp ) &
1092  .AND. ( sum(abs(omega(:)-a_dirk_ij(n_rk,:))) .EQ. 0.0_wp ) ) THEN
1093 
1094  ! The assembling coeffs are equal to the last step of the RK scheme
1095  q(1:n_vars,j,k) = q_rk(1:n_vars,j,k,n_rk)
1096 
1097  ELSE
1098 
1099  ! The assembling coeffs are different
1100  q(1:n_vars,j,k) = q0(1:n_vars,j,k) - dt * residual_term(1:n_vars,j,k)
1101 
1102  END IF
1103 
1104  negative_thickness_check:IF ( q(1,j,k) .LT. 0.0_wp ) THEN
1105 
1106  IF ( q(1,j,k) .GT. -1.e-7_wp ) THEN
1107 
1108  q(1,j,k) = 0.0_wp
1109  q(2:n_vars,j,k) = 0.0_wp
1110 
1111  ELSE
1112 
1113  WRITE(*,*) 'j,k,n_RK',j,k,n_rk
1114  WRITE(*,*) 'dt',dt
1115  WRITE(*,*) 'before imex_RK_solver: qc',q0(1:n_vars,j,k)
1116  IF ( q0(1,j,k) .GT. 0.0_wp ) THEN
1117 
1118  CALL qc_to_qp(q0(1:n_vars,j,k) , qp(1:n_vars+2,j,k))
1119  WRITE(*,*) 'before imex_RK_solver: qp',qp(1:n_vars+2,j,k)
1120 
1121  END IF
1122  WRITE(*,*) 'after imex_RK_solver: qc',q(1:n_vars,j,k)
1123 
1124  WRITE(*,*) 'divFlux(1,j,k,1:n_RK)',divflux(1,j,k,1:n_rk)
1125 
1126  WRITE(*,*) h_interface_x(1,j+1,k), h_interface_x(1,j,k)
1127  WRITE(*,*) qp_interfacer(1:n_vars,j,k)
1128  WRITE(*,*) qp(1:n_vars,j,k)
1129  WRITE(*,*) qp_interfacel(1:n_vars,j+1,k)
1130 
1131  WRITE(*,*) 'NH(1,j,k,1:n_RK)',nh(1,j,k,1:n_rk)
1132 
1133  READ(*,*)
1134 
1135  END IF
1136 
1137  END IF negative_thickness_check
1138 
1139  END DO assemble_sol
1140 
1141  !$OMP END PARALLEL DO
1142 
1143  RETURN
1144 
1145  END SUBROUTINE imex_rk_solver
1146 
1147  !******************************************************************************
1149  !
1156  !
1166  !
1170  !
1171  !******************************************************************************
1172 
1173  SUBROUTINE solve_rk_step( cell_fract_jk , dx_rel_jk , dy_rel_jk , qj, qj_old, &
1174  a_tilde, a_dirk, a_diag, rj_not_impl, divfluxj , nhj )
1176  USE parameters_2d, ONLY : max_nl_iter , tol_rel , tol_abs
1177 
1178  USE constitutive_2d, ONLY : qc_to_qp
1179 
1180  IMPLICIT NONE
1181 
1182  REAL(wp), INTENT(IN) :: cell_fract_jk
1183  REAL(wp), INTENT(IN) :: dx_rel_jk
1184  REAL(wp), INTENT(IN) :: dy_rel_jk
1185 
1186  REAL(wp), INTENT(INOUT) :: qj(n_vars)
1187  REAL(wp), INTENT(IN) :: qj_old(n_vars)
1188  REAL(wp), INTENT(IN) :: a_tilde(n_rk)
1189  REAL(wp), INTENT(IN) :: a_dirk(n_rk)
1190  REAL(wp), INTENT(IN) :: a_diag
1191  REAL(wp), INTENT(IN) :: Rj_not_impl(n_eqns)
1192  REAL(wp), INTENT(IN) :: divFluxj(n_eqns,n_rk)
1193  REAL(wp), INTENT(IN) :: NHj(n_eqns,n_rk)
1194 
1195  REAL(wp) :: qj_init(n_vars)
1196 
1197  REAL(wp) :: qj_org(n_vars) , qj_rel(n_vars)
1198 
1199  REAL(wp) :: left_matrix(n_eqns,n_vars)
1200  REAL(wp) :: right_term(n_eqns)
1201 
1202  REAL(wp) :: scal_f
1203 
1204  REAL(wp) :: coeff_f(n_eqns)
1205 
1206  REAL(wp) :: qj_rel_NR_old(n_vars)
1207  REAL(wp) :: scal_f_old
1208  REAL(wp) :: desc_dir(n_vars)
1209  REAL(wp) :: grad_f(n_vars)
1210 
1211  INTEGER :: pivot(n_vars)
1212 
1213  REAL(wp) :: left_matrix_small22(n_nh,n_nh)
1214  REAL(wp) :: left_matrix_small21(n_eqns-n_nh,n_nh)
1215  REAL(wp) :: left_matrix_small11(n_eqns-n_nh,n_vars-n_nh)
1216  ! REAL(wp) :: left_matrix_small12(n_nh,n_vars-n_nh)
1217 
1218  REAL(wp) :: desc_dir_small2(n_nh)
1219  INTEGER :: pivot_small2(n_nh)
1220 
1221  REAL(wp) :: desc_dir_small1(n_vars-n_nh)
1222 
1223  INTEGER :: ok
1224 
1225  INTEGER :: i
1226  INTEGER :: nl_iter
1227 
1228  REAL(wp), PARAMETER :: STPMX=100.0_wp
1229  REAL(wp) :: stpmax
1230  LOGICAL :: check
1231 
1232  REAL(wp), PARAMETER :: TOLF=1.e-10_wp , tolmin=1.e-6_wp
1233  REAL(wp) :: TOLX
1234 
1235  ! REAL(wp) :: qpj(n_vars+2)
1236 
1237  REAL(wp) :: desc_dir2(n_vars)
1238 
1239  REAL(wp) :: desc_dir_temp(n_vars)
1240 
1241  normalize_q = .true.
1242  normalize_f = .false.
1243  opt_search_nl = .true.
1244 
1245  coeff_f(1:n_eqns) = 1.0_wp
1246 
1247  grad_f(1:n_eqns) = 0.0_wp
1248 
1249  qj_init = qj
1250 
1251  ! normalize the functions of the nonlinear system
1252  IF ( normalize_f ) THEN
1253 
1254  qj = qj_old - dt * (matmul( divfluxj , a_tilde ) - matmul( nhj , a_dirk ))
1255 
1256  CALL eval_f( cell_fract_jk , dx_rel_jk , dy_rel_jk , qj , qj_old , &
1257  a_diag , coeff_f , rj_not_impl , right_term , scal_f )
1258 
1259  IF ( verbose_level .GE. 3 ) THEN
1260 
1261  WRITE(*,*) 'solve_rk_step: non-normalized right_term'
1262  WRITE(*,*) right_term
1263  WRITE(*,*) 'scal_f',scal_f
1264 
1265  END IF
1266 
1267  DO i=1,n_eqns
1268 
1269  IF ( abs(right_term(i)) .GE. 1.0_wp ) coeff_f(i) = 1.0_wp/right_term(i)
1270 
1271  END DO
1272 
1273  right_term = coeff_f * right_term
1274 
1275  scal_f = 0.5_wp * dot_product( right_term , right_term )
1276 
1277  IF ( verbose_level .GE. 3 ) THEN
1278  WRITE(*,*) 'solve_rk_step: after normalization',scal_f
1279  END IF
1280 
1281  END IF
1282 
1283  !---- normalize the conservative variables ------
1284 
1285  IF ( normalize_q ) THEN
1286 
1287  qj_org = qj
1288 
1289  qj_org = max( abs(qj_org) , 1.e-3_wp )
1290 
1291  ELSE
1292 
1293  qj_org(1:n_vars) = 1.0_wp
1294 
1295  END IF
1296 
1297  qj_rel = qj / qj_org
1298 
1299  ! -----------------------------------------------
1300 
1301  newton_raphson_loop:DO nl_iter=1,max_nl_iter
1302 
1303  tolx = epsilon(qj_rel)
1304 
1305  IF ( verbose_level .GE. 2 ) WRITE(*,*) 'solve_rk_step: nl_iter',nl_iter
1306 
1307  CALL eval_f( cell_fract_jk , dx_rel_jk , dy_rel_jk , qj , qj_old , &
1308  a_diag , coeff_f , rj_not_impl , right_term , scal_f )
1309 
1310  IF ( verbose_level .GE. 2 ) THEN
1311 
1312  WRITE(*,*) 'solve_rk_step: right_term',right_term
1313 
1314  END IF
1315 
1316  IF ( verbose_level .GE. 2 ) THEN
1317 
1318  WRITE(*,*) 'before_lnsrch: scal_f',scal_f
1319 
1320  END IF
1321 
1322  ! check the residual of the system
1323 
1324  IF ( maxval( abs( right_term(:) ) ) < tolf ) THEN
1325 
1326  IF ( verbose_level .GE. 3 ) WRITE(*,*) '1: check',check
1327  RETURN
1328 
1329  END IF
1330 
1331  IF ( ( normalize_f ) .AND. ( scal_f < 1.e-6_wp ) ) THEN
1332 
1333  IF ( verbose_level .GE. 3 ) WRITE(*,*) 'check scal_f',check
1334  RETURN
1335 
1336  END IF
1337 
1338  ! ---- evaluate the descent direction ------------------------------------
1339 
1340  IF ( count( implicit_flag ) .EQ. n_eqns ) THEN
1341 
1342  CALL eval_jacobian( cell_fract_jk , dx_rel_jk , dy_rel_jk , qj_rel , &
1343  qj_org, coeff_f , left_matrix )
1344 
1345  desc_dir_temp = - right_term
1346 
1347  IF ( wp .EQ. sp ) THEN
1348 
1349  CALL sgesv(n_eqns,1, left_matrix , n_eqns, pivot, desc_dir_temp , &
1350  n_eqns, ok)
1351 
1352  ELSE
1353 
1354  CALL dgesv(n_eqns,1, left_matrix , n_eqns, pivot, desc_dir_temp , &
1355  n_eqns, ok)
1356 
1357  END IF
1358 
1359  desc_dir = desc_dir_temp
1360 
1361  ELSE
1362 
1363  CALL eval_jacobian( cell_fract_jk , dx_rel_jk , dy_rel_jk , qj_rel , &
1364  qj_org,coeff_f , left_matrix )
1365 
1366  left_matrix_small11 = reshape(pack(left_matrix, mask11), &
1367  [n_eqns-n_nh,n_eqns-n_nh])
1368 
1369  ! not needed for computation
1370  !left_matrix_small12 = reshape(pack(left_matrix, mask12), &
1371  ! [n_nh,n_eqns-n_nh])
1372 
1373  left_matrix_small22 = reshape(pack(left_matrix, mask22), &
1374  [n_nh,n_nh])
1375 
1376  left_matrix_small21 = reshape(pack(left_matrix, mask21), &
1377  [n_eqns-n_nh,n_nh])
1378 
1379  desc_dir_small1 = pack( right_term, .NOT.implicit_flag )
1380  desc_dir_small2 = pack( right_term , implicit_flag )
1381 
1382  DO i=1,n_vars-n_nh
1383 
1384  desc_dir_small1(i) = desc_dir_small1(i) / left_matrix_small11(i,i)
1385 
1386  END DO
1387 
1388  desc_dir_small2 = desc_dir_small2 - &
1389  matmul( desc_dir_small1 , left_matrix_small21 )
1390 
1391  IF ( wp .EQ. sp ) THEN
1392 
1393  CALL sgesv(n_nh,1, left_matrix_small22 , n_nh , pivot_small2 , &
1394  desc_dir_small2 , n_nh, ok)
1395 
1396  ELSE
1397 
1398  CALL dgesv(n_nh,1, left_matrix_small22 , n_nh , pivot_small2 , &
1399  desc_dir_small2 , n_nh, ok)
1400 
1401  END IF
1402 
1403  desc_dir = unpack( - desc_dir_small2 , implicit_flag , 0.0_wp ) &
1404  + unpack( - desc_dir_small1 , .NOT.implicit_flag , 0.0_wp )
1405 
1406  END IF
1407 
1408  IF ( verbose_level .GE. 3 ) WRITE(*,*) 'desc_dir',desc_dir
1409 
1410  qj_rel_nr_old = qj_rel
1411  scal_f_old = scal_f
1412 
1413  IF ( ( opt_search_nl ) .AND. ( nl_iter .GT. 1 ) ) THEN
1414  ! Search for the step lambda giving a suffic. decrease in the solution
1415 
1416  stpmax = stpmx * max( sqrt( dot_product(qj_rel,qj_rel) ) , &
1417  dble( SIZE(qj_rel) ) )
1418 
1419  grad_f = matmul( right_term , left_matrix )
1420 
1421  desc_dir2 = desc_dir
1422 
1423  CALL lnsrch( cell_fract_jk , dx_rel_jk , dy_rel_jk , qj_rel_nr_old , &
1424  qj_org , qj_old , scal_f_old , grad_f , desc_dir , coeff_f , &
1425  qj_rel , scal_f , right_term , stpmax , check , rj_not_impl )
1426 
1427  ELSE
1428 
1429  qj_rel = qj_rel_nr_old + desc_dir
1430 
1431  qj = qj_rel * qj_org
1432 
1433  CALL eval_f( cell_fract_jk , dx_rel_jk , dy_rel_jk , qj , qj_old , &
1434  a_diag , coeff_f , rj_not_impl , right_term , scal_f )
1435 
1436  END IF
1437 
1438  IF ( verbose_level .GE. 2 ) WRITE(*,*) 'after_lnsrch: scal_f',scal_f
1439 
1440  qj = qj_rel * qj_org
1441 
1442  IF ( verbose_level .GE. 3 ) THEN
1443 
1444  WRITE(*,*) 'qj',qj
1445 
1446  END IF
1447 
1448  IF ( maxval( abs( right_term(:) ) ) < tolf ) THEN
1449 
1450  IF ( verbose_level .GE. 3 ) WRITE(*,*) '1: check',check
1451  check= .false.
1452  RETURN
1453 
1454  END IF
1455 
1456  IF (check) THEN
1457 
1458  check = ( maxval( abs(grad_f(:)) * max( abs( qj_rel(:) ),1.0_wp ) / &
1459  max( scal_f , 0.5_wp * SIZE(qj_rel) ) ) < tolmin )
1460 
1461  IF ( verbose_level .GE. 3 ) WRITE(*,*) '2: check',check
1462  ! RETURN
1463 
1464  END IF
1465 
1466  IF ( maxval( abs( qj_rel(:) - qj_rel_nr_old(:) ) / max( abs( qj_rel(:)) ,&
1467  1.0_wp ) ) < tolx ) THEN
1468 
1469  IF ( verbose_level .GE. 3 ) WRITE(*,*) 'check',check
1470  RETURN
1471 
1472  END IF
1473 
1474  END DO newton_raphson_loop
1475 
1476  RETURN
1477 
1478  END SUBROUTINE solve_rk_step
1479 
1480  !******************************************************************************
1482  !
1501  !******************************************************************************
1502 
1503  SUBROUTINE lnsrch( cell_fract_jk , dx_rel_jk , dy_rel_jk , qj_rel_NR_old , &
1504  qj_org , qj_old , scal_f_old , grad_f , desc_dir , coeff_f , qj_rel , &
1505  scal_f , right_term , stpmax , check , rj_not_impl )
1507  IMPLICIT NONE
1508 
1509  REAL(wp), INTENT(IN) :: cell_fract_jk
1510  REAL(wp), INTENT(IN) :: dx_rel_jk
1511  REAL(wp), INTENT(IN) :: dy_rel_jk
1512 
1514  REAL(wp), DIMENSION(:), INTENT(IN) :: qj_rel_NR_old
1515 
1517  REAL(wp), DIMENSION(:), INTENT(IN) :: qj_org
1518 
1520  REAL(wp), DIMENSION(:), INTENT(IN) :: qj_old
1521 
1523  REAL(wp), DIMENSION(:), INTENT(IN) :: grad_f
1524 
1526  REAL(wp), INTENT(IN) :: scal_f_old
1527 
1529  REAL(wp), DIMENSION(:), INTENT(INOUT) :: desc_dir
1530 
1531  REAL(wp), INTENT(IN) :: stpmax
1532 
1534  REAL(wp), DIMENSION(:), INTENT(IN) :: coeff_f
1535 
1537  REAL(wp), DIMENSION(:), INTENT(OUT) :: qj_rel
1538 
1540  REAL(wp), INTENT(OUT) :: scal_f
1541 
1543  REAL(wp), INTENT(OUT) :: right_term(n_eqns)
1544 
1546  LOGICAL, INTENT(OUT) :: check
1547 
1548  REAL(wp), INTENT(IN) :: Rj_not_impl(n_eqns)
1549 
1550  REAL(wp), PARAMETER :: TOLX=epsilon(qj_rel)
1551 
1552  INTEGER, DIMENSION(1) :: ndum
1553  REAL(wp) :: ALF , a,alam,alam2,alamin,b,disc
1554  REAL(wp) :: scal_f2
1555  REAL(wp) :: desc_dir_abs
1556  REAL(wp) :: rhs1 , rhs2 , slope, tmplam
1557 
1558  REAL(wp) :: scal_f_min , alam_min
1559 
1560  REAL(wp) :: qj(n_vars)
1561 
1562  alf = 1.0e-4_wp
1563 
1564  IF ( size(grad_f) == size(desc_dir) .AND. size(grad_f) == size(qj_rel) &
1565  .AND. size(qj_rel) == size(qj_rel_nr_old) ) THEN
1566 
1567  ndum = size(grad_f)
1568 
1569  ELSE
1570 
1571  WRITE(*,*) 'nrerror: an assert_eq failed with this tag:', 'lnsrch'
1572  stop 'program terminated by assert_eq4'
1573 
1574  END IF
1575 
1576  check = .false.
1577 
1578  desc_dir_abs = sqrt( dot_product(desc_dir,desc_dir) )
1579 
1580  IF ( desc_dir_abs > stpmax ) desc_dir(:) = desc_dir(:) * stpmax/desc_dir_abs
1581 
1582  slope = dot_product(grad_f,desc_dir)
1583 
1584  alamin = tolx / maxval(abs( desc_dir(:))/max( abs(qj_rel_nr_old(:)),1.0_wp ))
1585 
1586  IF ( alamin .EQ. 0.0_wp ) THEN
1587 
1588  qj_rel(:) = qj_rel_nr_old(:)
1589 
1590  RETURN
1591 
1592  END IF
1593 
1594  alam = 1.0_wp
1595 
1596  scal_f_min = scal_f_old
1597 
1598  optimal_step_search: DO
1599 
1600  IF ( verbose_level .GE. 4 ) THEN
1601 
1602  WRITE(*,*) 'alam',alam
1603 
1604  END IF
1605 
1606  qj_rel = qj_rel_nr_old + alam * desc_dir
1607 
1608  qj = qj_rel * qj_org
1609 
1610  CALL eval_f( cell_fract_jk , dx_rel_jk , dy_rel_jk , qj , qj_old , &
1611  a_diag , coeff_f , rj_not_impl , right_term , scal_f )
1612 
1613  IF ( verbose_level .GE. 4 ) THEN
1614 
1615  WRITE(*,*) 'lnsrch: effe_old,effe',scal_f_old,scal_f
1616  READ(*,*)
1617 
1618  END IF
1619 
1620  IF ( scal_f .LT. scal_f_min ) THEN
1621 
1622  scal_f_min = scal_f
1623  alam_min = alam
1624 
1625  END IF
1626 
1627  IF ( scal_f .LE. 0.9 * scal_f_old ) THEN
1628  ! sufficient function decrease
1629 
1630  IF ( verbose_level .GE. 4 ) THEN
1631 
1632  WRITE(*,*) 'sufficient function decrease'
1633 
1634  END IF
1635 
1636  EXIT optimal_step_search
1637 
1638  ELSE IF ( alam < alamin ) THEN
1639  ! convergence on Delta_x
1640 
1641  IF ( verbose_level .GE. 4 ) THEN
1642 
1643  WRITE(*,*) ' convergence on Delta_x',alam,alamin
1644 
1645  END IF
1646 
1647  qj_rel(:) = qj_rel_nr_old(:)
1648  scal_f = scal_f_old
1649  check = .true.
1650 
1651  EXIT optimal_step_search
1652 
1653  ! ELSE IF ( scal_f .LE. scal_f_old + ALF * alam * slope ) THEN
1654  ELSE
1655 
1656  IF ( alam .EQ. 1.0_wp ) THEN
1657 
1658  tmplam = - slope / ( 2.0_wp * ( scal_f - scal_f_old - slope ) )
1659 
1660  ELSE
1661 
1662  rhs1 = scal_f - scal_f_old - alam*slope
1663  rhs2 = scal_f2 - scal_f_old - alam2*slope
1664 
1665  a = ( rhs1/alam**2 - rhs2/alam2**2 ) / ( alam - alam2 )
1666  b = ( -alam2*rhs1/alam**2 + alam*rhs2/alam2**2 ) / ( alam - alam2 )
1667 
1668  IF ( a .EQ. 0.0_wp ) THEN
1669 
1670  tmplam = - slope / ( 2.0_wp * b )
1671 
1672  ELSE
1673 
1674  disc = b*b - 3.0_wp*a*slope
1675 
1676  IF ( disc .LT. 0.0_wp ) THEN
1677 
1678  tmplam = 0.5_wp * alam
1679 
1680  ELSE IF ( b .LE. 0.0_wp ) THEN
1681 
1682  tmplam = ( - b + sqrt(disc) ) / ( 3.0_wp * a )
1683 
1684  ELSE
1685 
1686  tmplam = - slope / ( b + sqrt(disc) )
1687 
1688  ENDIF
1689 
1690  END IF
1691 
1692  IF ( tmplam .GT. 0.5_wp * alam ) tmplam = 0.5_wp * alam
1693 
1694  END IF
1695 
1696  END IF
1697 
1698  alam2 = alam
1699  scal_f2 = scal_f
1700  alam = max( tmplam , 0.5_wp * alam )
1701 
1702  END DO optimal_step_search
1703 
1704  RETURN
1705 
1706  END SUBROUTINE lnsrch
1707 
1708  !******************************************************************************
1710  !
1723  !******************************************************************************
1724 
1725  SUBROUTINE eval_f( cell_fract_jk , dx_rel_jk , dy_rel_jk , qj , qj_old , &
1726  a_diag , coeff_f , rj_not_impl , f_nl , scal_f )
1729 
1730  IMPLICIT NONE
1731 
1732  REAL(wp), INTENT(IN) :: cell_fract_jk
1733  REAL(wp), INTENT(IN) :: dx_rel_jk
1734  REAL(wp), INTENT(IN) :: dy_rel_jk
1735 
1736  REAL(wp), INTENT(IN) :: qj(n_vars)
1737  REAL(wp), INTENT(IN) :: qj_old(n_vars)
1738  REAL(wp), INTENT(IN) :: a_diag
1739  REAL(wp), INTENT(IN) :: coeff_f(n_eqns)
1740  REAL(wp), INTENT(IN) :: Rj_not_impl(n_eqns)
1741 
1742  REAL(wp), INTENT(OUT) :: f_nl(n_eqns)
1743  REAL(wp), INTENT(OUT) :: scal_f
1744 
1745  REAL(wp) :: nh_term_impl(n_eqns)
1746  REAL(wp) :: Rj(n_eqns)
1747 
1748  CALL eval_nonhyperbolic_terms( cell_fract_jk, dx_rel_jk , dy_rel_jk , &
1749  r_qj = qj , r_nh_term_impl=nh_term_impl )
1750 
1751  rj = rj_not_impl - a_diag * nh_term_impl
1752 
1753  f_nl = qj - qj_old + dt * rj
1754 
1755  f_nl = coeff_f * f_nl
1756 
1757  scal_f = 0.5_wp * dot_product( f_nl , f_nl )
1758 
1759  RETURN
1760 
1761  END SUBROUTINE eval_f
1762 
1763  !******************************************************************************
1765  !
1768  !
1773  !
1777  !******************************************************************************
1778 
1779  SUBROUTINE eval_jacobian( cell_fract_jk , dx_rel_jk , dy_rel_jk , qj_rel , &
1780  qj_org , coeff_f, left_matrix)
1783 
1784  IMPLICIT NONE
1785 
1786  REAL(wp), INTENT(IN) :: cell_fract_jk
1787  REAL(wp), INTENT(IN) :: dx_rel_jk
1788  REAL(wp), INTENT(IN) :: dy_rel_jk
1789 
1790  REAL(wp), INTENT(IN) :: qj_rel(n_vars)
1791  REAL(wp), INTENT(IN) :: qj_org(n_vars)
1792  REAL(wp), INTENT(IN) :: coeff_f(n_eqns)
1793 
1794  REAL(wp), INTENT(OUT) :: left_matrix(n_eqns,n_vars)
1795 
1796  REAL(wp) :: Jacob_relax(n_eqns,n_vars)
1797  COMPLEX(wp) :: nh_terms_cmplx_impl(n_eqns)
1798  COMPLEX(wp) :: qj_cmplx(n_vars) , qj_rel_cmplx(n_vars)
1799  COMPLEX(wp) :: qj_rel_cmplx_init(n_vars)
1800 
1801  REAL(wp) :: h
1802 
1803  INTEGER :: i
1804 
1805  h = n_vars * epsilon(1.0_wp)
1806 
1807  ! initialize the matrix of the linearized system and the Jacobian
1808 
1809  left_matrix(1:n_eqns,1:n_vars) = 0.0_wp
1810  jacob_relax(1:n_eqns,1:n_vars) = 0.0_wp
1811 
1812  ! evaluate the jacobian of the non-hyperbolic terms
1813 
1814  DO i=1,n_vars
1815 
1816  qj_rel_cmplx_init(i) = cmplx(qj_rel(i),0.0_wp,wp)
1817 
1818  END DO
1819 
1820  DO i=1,n_vars
1821 
1822  left_matrix(i,i) = coeff_f(i) * qj_org(i)
1823 
1824  IF ( implicit_flag(i) ) THEN
1825 
1826  qj_rel_cmplx(1:n_vars) = qj_rel_cmplx_init(1:n_vars)
1827  qj_rel_cmplx(i) = cmplx(qj_rel(i), h,wp)
1828 
1829  qj_cmplx = qj_rel_cmplx * qj_org
1830 
1831  CALL eval_nonhyperbolic_terms( cell_fract_jk , dx_rel_jk , dy_rel_jk ,&
1832  c_qj = qj_cmplx , c_nh_term_impl = nh_terms_cmplx_impl )
1833 
1834  jacob_relax(1:n_eqns,i) = coeff_f(i) * &
1835  aimag(nh_terms_cmplx_impl) / h
1836 
1837  left_matrix(1:n_eqns,i) = left_matrix(1:n_eqns,i) - dt * a_diag &
1838  * jacob_relax(1:n_eqns,i)
1839 
1840  END IF
1841 
1842  END DO
1843 
1844  RETURN
1845 
1846  END SUBROUTINE eval_jacobian
1847 
1848  !******************************************************************************
1850  !
1855  !
1859  !
1863  !******************************************************************************
1864 
1865  SUBROUTINE eval_hyperbolic_terms( q_expl , qp_expl , divFlux_iRK )
1867  ! External variables
1868  USE geometry_2d, ONLY : dx,dy
1869  USE parameters_2d, ONLY : solver_scheme
1870 
1871  IMPLICIT NONE
1872 
1873  REAL(wp), INTENT(IN) :: q_expl(n_vars,comp_cells_x,comp_cells_y)
1874  REAL(wp), INTENT(IN) :: qp_expl(n_vars+2,comp_cells_x,comp_cells_y)
1875  REAL(wp), INTENT(OUT) :: divFlux_iRK(n_eqns,comp_cells_x,comp_cells_y)
1876 
1877  INTEGER :: l , i, j, k
1878 
1879  ! Linear reconstruction of the physical variables at the interfaces
1880  CALL reconstruction(q_expl,qp_expl)
1881 
1882  ! Evaluation of the maximum local speeds at the interfaces
1883  CALL eval_speeds
1884 
1885  ! Evaluation of the numerical fluxes
1886  SELECT CASE ( solver_scheme )
1887 
1888  CASE ("LxF")
1889 
1890  CALL eval_flux_lxf
1891 
1892  CASE ("GFORCE")
1893 
1894  CALL eval_flux_gforce
1895 
1896  CASE ("KT")
1897 
1898  CALL eval_flux_kt
1899 
1900  CASE ("UP")
1901 
1902  CALL eval_flux_up
1903 
1904  END SELECT
1905 
1906  !WRITE(*,*) 'H_interface_x(1,2,1)',H_interface_x(1,2,1)
1907  !WRITE(*,*) 'q_interfaceR(1,1,1)',q_interfaceR(1,1,1)
1908  !WRITE(*,*) 'qp_interfaceR(1,1,1)',qp_interfaceR(1,1,1)
1909  !WRITE(*,*) 'H_interface_x(1,1,1)',H_interface_x(1,1,1)
1910  !WRITE(*,*) 'H_interface_y(1,1,2)',H_interface_y(1,1,2)
1911  !WRITE(*,*) 'H_interface_y(1,1,1)',H_interface_y(1,1,1)
1912 
1913  !$OMP PARALLEL DO private(l,j,k,i)
1914 
1915  ! Advance in time the solution
1916  cells_loop:DO l = 1,solve_cells
1917 
1918  j = j_cent(l)
1919  k = k_cent(l)
1920 
1921  DO i=1,n_eqns
1922 
1923  divflux_irk(i,j,k) = 0.0_wp
1924 
1925  IF ( comp_cells_x .GT. 1 ) THEN
1926 
1927  divflux_irk(i,j,k) = divflux_irk(i,j,k) + &
1928  ( h_interface_x(i,j+1,k) - h_interface_x(i,j,k) ) / dx
1929 
1930  END IF
1931 
1932  IF ( comp_cells_y .GT. 1 ) THEN
1933 
1934  divflux_irk(i,j,k) = divflux_irk(i,j,k) + &
1935  ( h_interface_y(i,j,k+1) - h_interface_y(i,j,k) ) / dy
1936 
1937  END IF
1938 
1939  END DO
1940 
1941  END DO cells_loop
1942 
1943  !$OMP END PARALLEL DO
1944 
1945  RETURN
1946 
1947  END SUBROUTINE eval_hyperbolic_terms
1948 
1949  !******************************************************************************
1951  !
1957  !******************************************************************************
1958 
1959  SUBROUTINE eval_flux_up
1961  ! External procedures
1962  USE constitutive_2d, ONLY : eval_fluxes
1963 
1964  IMPLICIT NONE
1965 
1966  REAL(wp) :: fluxL(n_eqns)
1967  REAL(wp) :: fluxR(n_eqns)
1968  REAL(wp) :: fluxB(n_eqns)
1969  REAL(wp) :: fluxT(n_eqns)
1970 
1971  INTEGER :: j,k,l
1972 
1973  h_interface_x = 0.0_wp
1974  h_interface_y = 0.0_wp
1975 
1976  IF ( comp_cells_x .GT. 1 ) THEN
1977 
1978  DO l = 1,solve_interfaces_x
1979 
1980  j = j_stag_x(l)
1981  k = k_stag_x(l)
1982 
1983  CALL eval_fluxes( q_interfacel(1:n_vars,j,k) , &
1984  qp_interfacel(1:n_vars+2,j,k) , 1 , fluxl)
1985 
1986  CALL eval_fluxes( q_interfacer(1:n_vars,j,k) , &
1987  qp_interfacer(1:n_vars+2,j,k) , 1 , fluxr)
1988 
1989  IF ( ( q_interfacel(2,j,k) .GT. 0.0_wp ) .AND. &
1990  ( q_interfacer(2,j,k) .GE. 0.0_wp ) ) THEN
1991 
1992  h_interface_x(:,j,k) = fluxl
1993 
1994  ELSEIF ( ( q_interfacel(2,j,k) .LE. 0.0_wp ) .AND. &
1995  ( q_interfacer(2,j,k) .LT. 0.0_wp ) ) THEN
1996 
1997  h_interface_x(:,j,k) = fluxr
1998 
1999  ELSE
2000 
2001  h_interface_x(:,j,k) = 0.5_wp * ( fluxl + fluxr )
2002 
2003  END IF
2004 
2005  IF ( ( q_interfacel(2,j,k) .EQ. 0.0_wp ) .AND. &
2006  ( q_interfacer(2,j,k) .EQ. 0.0_wp ) ) THEN
2007 
2008  h_interface_x(1,j,k) = 0.0_wp
2009  h_interface_x(4:n_vars,j,k) = 0.0_wp
2010 
2011  END IF
2012 
2013  END DO
2014 
2015  END IF
2016 
2017 
2018  IF ( comp_cells_y .GT. 1 ) THEN
2019 
2020  DO l = 1,solve_interfaces_y
2021 
2022  j = j_stag_y(l)
2023  k = k_stag_y(l)
2024 
2025  CALL eval_fluxes( q_interfaceb(1:n_vars,j,k) , &
2026  qp_interfaceb(1:n_vars+2,j,k) , 2 , fluxb)
2027 
2028  CALL eval_fluxes( q_interfacet(1:n_vars,j,k) , &
2029  qp_interfacet(1:n_vars+2,j,k) ,2 , fluxt)
2030 
2031  IF ( ( q_interfaceb(3,j,k) .GT. 0.0_wp ) .AND. &
2032  ( q_interfacet(3,j,k) .GE. 0.0_wp ) ) THEN
2033 
2034  h_interface_y(:,j,k) = fluxb
2035 
2036  ELSEIF ( ( q_interfaceb(3,j,k) .LE. 0.0_wp ) .AND. &
2037  ( q_interfacet(3,j,k) .LT. 0.0_wp ) ) THEN
2038 
2039  h_interface_y(:,j,k) = fluxt
2040 
2041  ELSE
2042 
2043  h_interface_y(:,j,k) = 0.5_wp * ( fluxb + fluxt )
2044 
2045  END IF
2046 
2047  ! In the equation for mass and for trasnport (T,alphas) if the
2048  ! velocities at the interfaces are null, then the flux is null
2049  IF ( ( q_interfaceb(3,j,k) .EQ. 0.0_wp ) .AND. &
2050  ( q_interfacet(3,j,k) .EQ. 0.0_wp ) ) THEN
2051 
2052  h_interface_y(1,j,k) = 0.0_wp
2053  h_interface_y(4:n_vars,j,k) = 0.0_wp
2054 
2055  END IF
2056 
2057  END DO
2058 
2059  END IF
2060 
2061  RETURN
2062 
2063  END SUBROUTINE eval_flux_up
2064 
2065 
2066  !******************************************************************************
2068  !
2074  !******************************************************************************
2075 
2076  SUBROUTINE eval_flux_kt
2078  ! External procedures
2079  USE constitutive_2d, ONLY : eval_fluxes
2080 
2081  IMPLICIT NONE
2082 
2083  REAL(wp) :: fluxL(n_eqns)
2084  REAL(wp) :: fluxR(n_eqns)
2085  REAL(wp) :: fluxB(n_eqns)
2086  REAL(wp) :: fluxT(n_eqns)
2087 
2088  REAL(wp) :: flux_avg_x(n_eqns)
2089  REAL(wp) :: flux_avg_y(n_eqns)
2090 
2091  INTEGER :: i,j,k,l
2092 
2093  ! WRITE(*,*) 'eval_flux_KT: qp_interfaceR(1,1,1)',qp_interfaceR(1,1,1)
2094 
2095 
2096  !H_interface_x = 0.0_wp
2097  !H_interface_y = 0.0_wp
2098 
2099  !$OMP PARALLEL
2100 
2101  IF ( comp_cells_x .GT. 1 ) THEN
2102 
2103  !$OMP DO private(j,k,i,fluxL,fluxR,flux_avg_x)
2104 
2105  interfaces_x_loop:DO l = 1,solve_interfaces_x
2106 
2107  j = j_stag_x(l)
2108  k = k_stag_x(l)
2109 
2110  CALL eval_fluxes( q_interfacel(1:n_vars,j,k) , &
2111  qp_interfacel(1:n_vars+2,j,k) , 1 , fluxl)
2112 
2113  CALL eval_fluxes( q_interfacer(1:n_vars,j,k) , &
2114  qp_interfacer(1:n_vars+2,j,k) , 1 , fluxr)
2115 
2116  CALL average_kt( a_interface_xneg(:,j,k), a_interface_xpos(:,j,k) , &
2117  fluxl , fluxr , flux_avg_x )
2118 
2119  eqns_loop:DO i=1,n_eqns
2120 
2121  IF ( a_interface_xneg(i,j,k) .EQ. a_interface_xpos(i,j,k) ) THEN
2122 
2123  h_interface_x(i,j,k) = 0.0_wp
2124 
2125  ELSE
2126 
2127  h_interface_x(i,j,k) = flux_avg_x(i) &
2128  + ( a_interface_xpos(i,j,k) * a_interface_xneg(i,j,k) ) &
2129  / ( a_interface_xpos(i,j,k) - a_interface_xneg(i,j,k) ) &
2130  * ( q_interfacer(i,j,k) - q_interfacel(i,j,k) )
2131 
2132  END IF
2133 
2134  ENDDO eqns_loop
2135 
2136  ! In the equation for mass and for trasnport (T,alphas) if the
2137  ! velocities at the interfaces are null, then the flux is null
2138  IF ( ( qp_interfacel(2,j,k) .EQ. 0.0_wp ) .AND. &
2139  ( qp_interfacer(2,j,k) .EQ. 0.0_wp ) ) THEN
2140 
2141  h_interface_x(1,j,k) = 0.0_wp
2142  h_interface_x(4:n_vars,j,k) = 0.0_wp
2143 
2144  END IF
2145 
2146  END DO interfaces_x_loop
2147 
2148  !$OMP END DO NOWAIT
2149 
2150  END IF
2151 
2152 
2153  IF ( comp_cells_y .GT. 1 ) THEN
2154 
2155  !$OMP DO private(j,k,i,fluxB,fluxT,flux_avg_y)
2156 
2157  interfaces_y_loop:DO l = 1,solve_interfaces_y
2158 
2159  j = j_stag_y(l)
2160  k = k_stag_y(l)
2161 
2162  CALL eval_fluxes( q_interfaceb(1:n_vars,j,k) , &
2163  qp_interfaceb(1:n_vars+2,j,k) , 2 , fluxb)
2164 
2165  CALL eval_fluxes( q_interfacet(1:n_vars,j,k) , &
2166  qp_interfacet(1:n_vars+2,j,k) , 2 , fluxt)
2167 
2168  CALL average_kt( a_interface_yneg(:,j,k) , &
2169  a_interface_ypos(:,j,k) , fluxb , fluxt , flux_avg_y )
2170 
2171  DO i=1,n_eqns
2172 
2173  IF ( a_interface_yneg(i,j,k) .EQ. a_interface_ypos(i,j,k) ) THEN
2174 
2175  h_interface_y(i,j,k) = 0.0_wp
2176 
2177  ELSE
2178 
2179  h_interface_y(i,j,k) = flux_avg_y(i) &
2180  + ( a_interface_ypos(i,j,k) * a_interface_yneg(i,j,k) ) &
2181  / ( a_interface_ypos(i,j,k) - a_interface_yneg(i,j,k) ) &
2182  * ( q_interfacet(i,j,k) - q_interfaceb(i,j,k) )
2183 
2184  END IF
2185 
2186  END DO
2187 
2188  ! In the equation for mass and for trasnport (T,alphas) if the
2189  ! velocities at the interfaces are null, then the flux is null
2190  IF ( ( q_interfaceb(3,j,k) .EQ. 0.0_wp ) .AND. &
2191  ( q_interfacet(3,j,k) .EQ. 0.0_wp ) ) THEN
2192 
2193  h_interface_y(1,j,k) = 0.0_wp
2194  h_interface_y(4:n_vars,j,k) = 0.0_wp
2195 
2196  END IF
2197 
2198  END DO interfaces_y_loop
2199 
2200  !$OMP END DO
2201 
2202  END IF
2203 
2204  !$OMP END PARALLEL
2205 
2206  RETURN
2207 
2208  END SUBROUTINE eval_flux_kt
2209 
2210  !******************************************************************************
2212  !
2223  !******************************************************************************
2224 
2225  SUBROUTINE average_kt( a1 , a2 , w1 , w2 , w_avg )
2227  IMPLICIT NONE
2228 
2229  REAL(wp), INTENT(IN) :: a1(:) , a2(:)
2230  REAL(wp), INTENT(IN) :: w1(:) , w2(:)
2231  REAL(wp), INTENT(OUT) :: w_avg(:)
2232 
2233  INTEGER :: n
2234  INTEGER :: i
2235 
2236  n = SIZE( a1 )
2237 
2238  DO i=1,n
2239 
2240  IF ( a1(i) .EQ. a2(i) ) THEN
2241 
2242  w_avg(i) = 0.5_wp * ( w1(i) + w2(i) )
2243  w_avg(i) = 0.0_wp
2244 
2245  ELSE
2246 
2247  w_avg(i) = ( a2(i) * w1(i) - a1(i) * w2(i) ) / ( a2(i) - a1(i) )
2248 
2249  END IF
2250 
2251  END DO
2252 
2253  RETURN
2254 
2255  END SUBROUTINE average_kt
2256 
2257  !******************************************************************************
2262  !******************************************************************************
2263 
2264  SUBROUTINE eval_flux_gforce
2266  ! to be implemented
2267  WRITE(*,*) 'method not yet implemented in 2-d case'
2268 
2269  END SUBROUTINE eval_flux_gforce
2270 
2271  !******************************************************************************
2276  !******************************************************************************
2277 
2278  SUBROUTINE eval_flux_lxf
2280  ! to be implemented
2281  WRITE(*,*) 'method not yet implemented in 2-d case'
2282 
2283  END SUBROUTINE eval_flux_lxf
2284 
2285 
2286  !******************************************************************************
2288  !
2299  !******************************************************************************
2300 
2301  SUBROUTINE reconstruction(q_expl,qp_expl)
2303  ! External procedures
2305  USE constitutive_2d, ONLY : eval_source_bdry
2306  USE parameters_2d, ONLY : limiter
2307 
2308  ! External variables
2309  USE geometry_2d, ONLY : x_comp , x_stag , y_comp , y_stag , dx , dx2 , dy , &
2310  dy2
2311 
2312  USE geometry_2d, ONLY : sourcew , sourcee , sourcen , sources
2317 
2318  USE parameters_2d, ONLY : reconstr_coeff
2319 
2320  USE geometry_2d, ONLY : minmod
2321 
2322  IMPLICIT NONE
2323 
2324  REAL(wp), INTENT(IN) :: q_expl(:,:,:)
2325  REAL(wp), INTENT(IN) :: qp_expl(:,:,:)
2326 
2327  REAL(wp) :: qrecW(n_vars+2)
2328  REAL(wp) :: qrecE(n_vars+2)
2329  REAL(wp) :: qrecS(n_vars+2)
2330  REAL(wp) :: qrecN(n_vars+2)
2331 
2332  REAL(wp) :: source_bdry(n_vars+2)
2333  REAL(wp) :: qrec_prime_x(n_vars+2)
2334  REAL(wp) :: qrec_prime_y(n_vars+2)
2335 
2336  REAL(wp) :: qp2recW(3) , qp2recE(3)
2337  REAL(wp) :: qp2recS(3) , qp2recN(3)
2338 
2339  REAL(wp) :: qrec_stencil(3)
2340  REAL(wp) :: x_stencil(3)
2341  REAL(wp) :: y_stencil(3)
2342 
2343  INTEGER :: l,j,k
2344  INTEGER :: i
2345 
2346  REAL(wp) :: dq
2347 
2348  !$OMP PARALLEL DO private(j,k,i,qrecW,qrecE,qrecS,qrecN,x_stencil,y_stencil,&
2349  !$OMP & qrec_stencil,qrec_prime_x,qrec_prime_y,qp2recW,qp2recE,qp2recS, &
2350  !$OMP & qp2recN,source_bdry,dq)
2351 
2352  DO l = 1,solve_cells
2353 
2354  j = j_cent(l)
2355  k = k_cent(l)
2356 
2357  qrecw(1:n_vars+2) = qp_expl(1:n_vars+2,j,k)
2358  qrece(1:n_vars+2) = qp_expl(1:n_vars+2,j,k)
2359  qrecs(1:n_vars+2) = qp_expl(1:n_vars+2,j,k)
2360  qrecn(1:n_vars+2) = qp_expl(1:n_vars+2,j,k)
2361 
2362  x_stencil(2) = x_comp(j)
2363  y_stencil(2) = y_comp(k)
2364 
2365  vars_loop:DO i=1,n_vars
2366 
2367  qrec_stencil(2) = qp_expl(i,j,k)
2368 
2369  ! x direction
2370  check_comp_cells_x:IF ( comp_cells_x .GT. 1 ) THEN
2371 
2372  ! west boundary
2373  check_x_boundary:IF (j.EQ.1) THEN
2374 
2375  IF ( bcw(i)%flag .EQ. 0 ) THEN
2376 
2377  x_stencil(1) = x_stag(1)
2378  x_stencil(3) = x_comp(j+1)
2379 
2380  qrec_stencil(1) = bcw(i)%value
2381  qrec_stencil(3) = qp_expl(i,j+1,k)
2382 
2383  CALL limit( qrec_stencil , x_stencil , limiter(i) , &
2384  qrec_prime_x(i) )
2385 
2386  ELSEIF ( bcw(i)%flag .EQ. 1 ) THEN
2387 
2388  qrec_prime_x(i) = bcw(i)%value
2389 
2390  ELSEIF ( bcw(i)%flag .EQ. 2 ) THEN
2391 
2392  qrec_prime_x(i) = ( qp_expl(i,2,k) - qp_expl(i,1,k) ) / dx
2393 
2394  END IF
2395 
2396  !east boundary
2397  ELSEIF (j.EQ.comp_cells_x) THEN
2398 
2399  IF ( bce(i)%flag .EQ. 0 ) THEN
2400 
2401  qrec_stencil(3) = bce(i)%value
2402  qrec_stencil(1)= qp_expl(i,j-1,k)
2403 
2404  x_stencil(3) = x_stag(comp_interfaces_x)
2405  x_stencil(1) = x_comp(j-1)
2406 
2407  CALL limit( qrec_stencil , x_stencil , limiter(i) , &
2408  qrec_prime_x(i) )
2409 
2410  ELSEIF ( bce(i)%flag .EQ. 1 ) THEN
2411 
2412  qrec_prime_x(i) = bce(i)%value
2413 
2414  ELSEIF ( bce(i)%flag .EQ. 2 ) THEN
2415 
2416  qrec_prime_x(i) = ( qp_expl(i,comp_cells_x,k) - &
2417  qp_expl(i,comp_cells_x-1,k) ) / dx
2418 
2419  END IF
2420 
2421  ! internal x cells
2422  ELSE
2423 
2424  x_stencil(1) = x_comp(j-1)
2425  x_stencil(3) = x_comp(j+1)
2426 
2427  qrec_stencil(1) = qp_expl(i,j-1,k)
2428  qrec_stencil(3) = qp_expl(i,j+1,k)
2429 
2430  CALL limit( qrec_stencil , x_stencil , limiter(i) , &
2431  qrec_prime_x(i) )
2432 
2433  ENDIF check_x_boundary
2434 
2435  dq = reconstr_coeff* dx2 * qrec_prime_x(i)
2436 
2437  qrecw(i) = qrec_stencil(2) - dq
2438  qrece(i) = qrec_stencil(2) + dq
2439 
2440  END IF check_comp_cells_x
2441 
2442  ! y-direction
2443  check_comp_cells_y:IF ( comp_cells_y .GT. 1 ) THEN
2444 
2445  ! South boundary
2446  check_y_boundary:IF (k.EQ.1) THEN
2447 
2448  IF ( bcs(i)%flag .EQ. 0 ) THEN
2449 
2450  y_stencil(1) = y_stag(1)
2451  y_stencil(3) = y_comp(k+1)
2452 
2453  qrec_stencil(1) = bcs(i)%value
2454  qrec_stencil(3) = qp_expl(i,j,k+1)
2455 
2456  CALL limit( qrec_stencil , y_stencil , limiter(i) , &
2457  qrec_prime_y(i) )
2458 
2459  ELSEIF ( bcs(i)%flag .EQ. 1 ) THEN
2460 
2461  qrec_prime_y(i) = bcs(i)%value
2462 
2463  ELSEIF ( bcs(i)%flag .EQ. 2 ) THEN
2464 
2465  qrec_prime_y(i) = ( qp_expl(i,j,2) - qp_expl(i,j,1) ) / dy
2466 
2467  END IF
2468 
2469  ! North boundary
2470  ELSEIF ( k .EQ. comp_cells_y ) THEN
2471 
2472  IF ( bcn(i)%flag .EQ. 0 ) THEN
2473 
2474  y_stencil(3) = y_stag(comp_interfaces_y)
2475  y_stencil(1) = y_comp(k-1)
2476 
2477  qrec_stencil(3) = bcn(i)%value
2478  qrec_stencil(1)= qp_expl(i,j,k-1)
2479 
2480  CALL limit( qrec_stencil , y_stencil , limiter(i) , &
2481  qrec_prime_y(i) )
2482 
2483  ELSEIF ( bcn(i)%flag .EQ. 1 ) THEN
2484 
2485  qrec_prime_y(i) = bcn(i)%value
2486 
2487  ELSEIF ( bcn(i)%flag .EQ. 2 ) THEN
2488 
2489  qrec_prime_y(i) = ( qp_expl(i,j,comp_cells_y) - &
2490  qp_expl(i,j,comp_cells_y-1) ) / dy
2491 
2492  END IF
2493 
2494  ! Internal y cells
2495  ELSE
2496 
2497  y_stencil(1) = y_comp(k-1)
2498  y_stencil(3) = y_comp(k+1)
2499 
2500  qrec_stencil(1) = qp_expl(i,j,k-1)
2501  qrec_stencil(3) = qp_expl(i,j,k+1)
2502 
2503  CALL limit( qrec_stencil , y_stencil , limiter(i) , &
2504  qrec_prime_y(i) )
2505 
2506  ENDIF check_y_boundary
2507 
2508  dq = reconstr_coeff* dy2 * qrec_prime_y(i)
2509 
2510  qrecs(i) = qrec_stencil(2) - dq
2511  qrecn(i) = qrec_stencil(2) + dq
2512 
2513  ENDIF check_comp_cells_y
2514 
2515  ENDDO vars_loop
2516 
2517  add_vars_loop:DO i=n_vars+1,n_vars+2
2518  ! reconstruction on u and v with same limiters of hu,hv
2519 
2520  ! x direction
2521  check_comp_cells_x2:IF ( comp_cells_x .GT. 1 ) THEN
2522 
2523  IF ( (j .GT. 1) .AND. (j .LT. comp_cells_x) ) THEN
2524 
2525  x_stencil(1:3) = x_comp(j-1:j+1)
2526  qrec_stencil(1:3) = qp_expl(i,j-1:j+1,k)
2527 
2528  CALL limit( qrec_stencil , x_stencil , limiter(i) , &
2529  qrec_prime_x(i) )
2530 
2531  dq = reconstr_coeff*dx2*qrec_prime_x(i)
2532 
2533  qrecw(i) = qrec_stencil(2) - dq
2534  qrece(i) = qrec_stencil(2) + dq
2535 
2536  END IF
2537 
2538  END IF check_comp_cells_x2
2539 
2540  ! y-direction
2541  check_comp_cells_y2:IF ( comp_cells_y .GT. 1 ) THEN
2542 
2543  IF ( ( k .GT. 1 ) .AND. ( k .LT. comp_cells_y ) ) THEN
2544 
2545  y_stencil(1:3) = y_comp(k-1:k+1)
2546  qrec_stencil = qp_expl(i,j,k-1:k+1)
2547 
2548  CALL limit( qrec_stencil , y_stencil , limiter(i) , &
2549  qrec_prime_y(i) )
2550 
2551  dq = reconstr_coeff*dy2*qrec_prime_y(i)
2552 
2553  qrecs(i) = qrec_stencil(2) - dq
2554  qrecn(i) = qrec_stencil(2) + dq
2555 
2556  ENDIF
2557 
2558  ENDIF check_comp_cells_y2
2559 
2560  ENDDO add_vars_loop
2561 
2562 
2563  IF ( comp_cells_x .GT. 1 ) THEN
2564 
2565  IF ( ( j .GT. 1 ) .AND. ( j .LT. comp_cells_x ) ) THEN
2566 
2567  IF ( q_expl(1,j,k) .EQ. 0.0_wp ) THEN
2568 
2569  ! In the internal cell, if thickness h is 0 at the center
2570  ! of the cell, then all the variables are 0 at the center
2571  ! and at the interfaces (no conversion back is needed from
2572  ! reconstructed to conservative)
2573  q_interfacer(:,j,k) = 0.0_wp
2574  q_interfacel(:,j+1,k) = 0.0_wp
2575 
2576  qp_interfacer(1:3,j,k) = 0.0_wp
2577  qp_interfacer(4:n_vars,j,k) = qrecw(4:n_vars)
2578  qp_interfacer(n_vars+1:n_vars+2,j,k) = 0.0_wp
2579 
2580  qp_interfacel(1:3,j+1,k) = 0.0_wp
2581  qp_interfacel(4:n_vars,j+1,k) = qrece(4:n_vars)
2582  qp_interfacel(n_vars+1:n_vars+2,j+1,k) = 0.0_wp
2583 
2584  END IF
2585 
2586  END IF
2587 
2588  IF ( j.EQ.1 ) THEN
2589 
2590  ! Dirichelet boundary condition at the west of the domain
2591  DO i=1,n_vars
2592 
2593  IF ( bcw(i)%flag .EQ. 0 ) THEN
2594 
2595  qrecw(i) = bcw(i)%value
2596 
2597  END IF
2598 
2599  ENDDO
2600 
2601  DO i=n_vars+1,n_vars+2
2602 
2603  CALL qp_to_qp2( qrecw(1:n_vars) , qp2recw )
2604  qrecw(i) = qp2recw(i-n_vars+1)
2605 
2606  CALL qp_to_qp2( qrece(1:n_vars) , qp2rece )
2607  qrece(i) = qp2rece(i-n_vars+1)
2608 
2609  END DO
2610 
2611  ELSEIF ( j.EQ.comp_cells_x ) THEN
2612 
2613  ! Dirichelet boundary condition at the east of the domain
2614  DO i=1,n_vars
2615 
2616  IF ( bce(i)%flag .EQ. 0 ) THEN
2617 
2618  qrece(i) = bce(i)%value
2619 
2620  END IF
2621 
2622  ENDDO
2623 
2624  DO i=n_vars+1,n_vars+2
2625 
2626  CALL qp_to_qp2( qrecw(1:n_vars) , qp2recw )
2627  qrecw(i) = qp2recw(i-n_vars+1)
2628 
2629  CALL qp_to_qp2( qrece(1:n_vars) , qp2rece )
2630  qrece(i) = qp2rece(i-n_vars+1)
2631 
2632  END DO
2633 
2634  ELSE
2635 
2636  END IF
2637 
2638  CALL qp_to_qc( qrecw,q_interfacer(:,j,k) )
2639  CALL qp_to_qc( qrece,q_interfacel(:,j+1,k) )
2640 
2641  qp_interfacer(1:n_vars+2,j,k) = qrecw(1:n_vars+2)
2642  qp_interfacel(1:n_vars+2,j+1,k) = qrece(1:n_vars+2)
2643 
2644  IF ( j.EQ.1 ) THEN
2645 
2646  ! Interface value at the left of first x-interface (external)
2647  q_interfacel(:,j,k) = q_interfacer(:,j,k)
2648  qp_interfacel(:,j,k) = qp_interfacer(:,j,k)
2649 
2650  !WRITE(*,*) 'q_interfaceL(:,j,k)',q_interfaceL(:,j,k)
2651  !READ(*,*)
2652 
2653  ELSEIF ( j.EQ.comp_cells_x ) THEN
2654 
2655  ! Interface value at the right of last x-interface (external)
2656  q_interfacer(:,j+1,k) = q_interfacel(:,j+1,k)
2657  qp_interfacer(:,j+1,k) = qp_interfacel(:,j+1,k)
2658 
2659  ELSE
2660 
2661  END IF
2662 
2663  ELSE
2664 
2665  ! for case comp_cells_x = 1
2666  q_interfacer(1:n_vars,j,k) = q_expl(1:n_vars,j,k)
2667  q_interfacel(1:n_vars,j+1,k) = q_expl(1:n_vars,j,k)
2668 
2669  qp_interfacer(1:n_vars+2,j,k) = qp_expl(1:n_vars+2,j,k)
2670  qp_interfacel(1:n_vars+2,j+1,k) = qp_expl(1:n_vars+2,j,k)
2671 
2672  END IF
2673 
2674  IF ( comp_cells_y .GT. 1 ) THEN
2675 
2676  IF ( ( k .GT. 1 ) .AND. ( k .LT. comp_cells_y ) ) THEN
2677 
2678  IF ( q_expl(1,j,k) .EQ. 0.0_wp ) THEN
2679 
2680  ! In the internal cell, if thickness h is 0 at the center
2681  ! of the cell, then all the variables are 0 at the center
2682  ! and at the interfaces (no conversion back is needed from
2683  ! reconstructed to conservative)
2684 
2685  q_interfacet(:,j,k) = 0.0_wp
2686  q_interfaceb(:,j,k+1) = 0.0_wp
2687 
2688  qp_interfacet(1:3,j,k) = 0.0_wp
2689  qp_interfacet(4:n_vars,j,k) = qrecs(4:n_vars)
2690  qp_interfacet(n_vars+1:n_vars+2,j,k) = 0.0_wp
2691 
2692  qp_interfaceb(1:3,j,k+1) = 0.0_wp
2693  qp_interfaceb(4:n_vars,j,k+1) = qrecn(4:n_vars)
2694  qp_interfaceb(n_vars+1:n_vars+2,j,k+1) = 0.0_wp
2695 
2696  END IF
2697 
2698  END IF
2699 
2700  IF ( k .EQ. 1 ) THEN
2701 
2702  ! Dirichelet boundary condition at the south of the domain
2703  DO i=1,n_vars
2704 
2705  IF ( bcs(i)%flag .EQ. 0 ) THEN
2706 
2707  qrecs(i) = bcs(i)%value
2708 
2709  END IF
2710 
2711  ENDDO
2712 
2713  DO i=n_vars+1,n_vars+2
2714 
2715  CALL qp_to_qp2( qrecs(1:n_vars) , qp2recs )
2716  qrecs(i) = qp2recs(i-n_vars+1)
2717 
2718  CALL qp_to_qp2( qrecn(1:n_vars) , qp2recn )
2719  qrecn(i) = qp2recn(i-n_vars+1)
2720 
2721  END DO
2722 
2723  ELSEIF ( k .EQ. comp_cells_y ) THEN
2724 
2725  ! Dirichelet boundary condition at the north of the domain
2726  DO i=1,n_vars
2727 
2728  IF ( bcn(i)%flag .EQ. 0 ) THEN
2729 
2730  qrecn(i) = bcn(i)%value
2731 
2732  END IF
2733 
2734  ENDDO
2735 
2736  DO i=n_vars+1,n_vars+2
2737 
2738  CALL qp_to_qp2( qrecs(1:n_vars) , qp2recs )
2739  qrecs(i) = qp2recs(i-n_vars+1)
2740 
2741  CALL qp_to_qp2( qrecn(1:n_vars) , qp2recn )
2742  qrecn(i) = qp2recn(i-n_vars+1)
2743 
2744  END DO
2745 
2746  ELSE
2747 
2748  END IF
2749 
2750  CALL qp_to_qc( qrecs, q_interfacet(:,j,k))
2751  CALL qp_to_qc( qrecn, q_interfaceb(:,j,k+1))
2752 
2753  qp_interfacet(1:n_vars+2,j,k) = qrecs(1:n_vars+2)
2754  qp_interfaceb(1:n_vars+2,j,k+1) = qrecn(1:n_vars+2)
2755 
2756  IF ( k .EQ. 1 ) THEN
2757 
2758  ! Interface value at the bottom of first y-interface (external)
2759  q_interfaceb(:,j,k) = q_interfacet(:,j,k)
2760  qp_interfaceb(:,j,k) = qp_interfacet(:,j,k)
2761 
2762  ELSEIF ( k .EQ. comp_cells_y ) THEN
2763 
2764  ! Interface value at the top of last y-interface (external)
2765  q_interfacet(:,j,k+1) = q_interfaceb(:,j,k+1)
2766  qp_interfacet(:,j,k+1) = qp_interfaceb(:,j,k+1)
2767 
2768  ELSE
2769 
2770  END IF
2771 
2772  ELSE
2773 
2774  ! case comp_cells_y = 1
2775 
2776  q_interfaceb(:,j,k) = q_expl(:,j,k)
2777  q_interfacet(:,j,k) = q_expl(:,j,k)
2778  q_interfaceb(:,j,k+1) = q_expl(:,j,k)
2779  q_interfacet(:,j,k+1) = q_expl(:,j,k)
2780 
2781  qp_interfaceb(:,j,k) = qp_expl(:,j,k)
2782  qp_interfacet(:,j,k) = qp_expl(:,j,k)
2783  qp_interfaceb(:,j,k+1) = qp_expl(:,j,k)
2784  qp_interfacet(:,j,k+1) = qp_expl(:,j,k)
2785 
2786  END IF
2787 
2788  END DO
2789 
2790  !$OMP END PARALLEL DO
2791 
2792  RETURN
2793 
2794  END SUBROUTINE reconstruction
2795 
2796 
2797  !******************************************************************************
2799  !
2805  !******************************************************************************
2806 
2807  SUBROUTINE eval_speeds
2809  ! External procedures
2811 
2812  IMPLICIT NONE
2813 
2814  REAL(wp) :: abslambdaL_min(n_vars) , abslambdaL_max(n_vars)
2815  REAL(wp) :: abslambdaR_min(n_vars) , abslambdaR_max(n_vars)
2816  REAL(wp) :: abslambdaB_min(n_vars) , abslambdaB_max(n_vars)
2817  REAL(wp) :: abslambdaT_min(n_vars) , abslambdaT_max(n_vars)
2818  REAL(wp) :: min_r(n_vars) , max_r(n_vars)
2819 
2820  INTEGER :: j,k,l
2821 
2822  !$OMP PARALLEL
2823 
2824  IF ( comp_cells_x .GT. 1 ) THEN
2825 
2826  !$OMP DO private(j , k , abslambdaL_min , abslambdaL_max , &
2827  !$OMP & abslambdaR_min , abslambdaR_max , min_r , max_r )
2828 
2829  x_interfaces_loop:DO l = 1,solve_interfaces_x
2830 
2831  j = j_stag_x(l)
2832  k = k_stag_x(l)
2833 
2834  CALL eval_local_speeds_x( qp_interfacel(:,j,k) , abslambdal_min , &
2835  abslambdal_max )
2836 
2837  CALL eval_local_speeds_x( qp_interfacer(:,j,k) , abslambdar_min , &
2838  abslambdar_max )
2839 
2840  min_r = min(abslambdal_min , abslambdar_min , 0.0_wp)
2841  max_r = max(abslambdal_max , abslambdar_max , 0.0_wp)
2842 
2843  a_interface_xneg(:,j,k) = min_r
2844  a_interface_xpos(:,j,k) = max_r
2845 
2846  END DO x_interfaces_loop
2847 
2848  !$OMP END DO NOWAIT
2849 
2850  END IF
2851 
2852  IF ( comp_cells_y .GT. 1 ) THEN
2853 
2854  !$OMP DO private(j , k , abslambdaB_min , abslambdaB_max , &
2855  !$OMP & abslambdaT_min , abslambdaT_max , min_r , max_r )
2856 
2857  y_interfaces_loop:DO l = 1,solve_interfaces_y
2858 
2859  j = j_stag_y(l)
2860  k = k_stag_y(l)
2861 
2862  CALL eval_local_speeds_y( qp_interfaceb(:,j,k) , abslambdab_min , &
2863  abslambdab_max )
2864 
2865  CALL eval_local_speeds_y( qp_interfacet(:,j,k) , abslambdat_min , &
2866  abslambdat_max )
2867 
2868  min_r = min(abslambdab_min , abslambdat_min , 0.0_wp)
2869  max_r = max(abslambdab_max , abslambdat_max , 0.0_wp)
2870 
2871  a_interface_yneg(:,j,k) = min_r
2872  a_interface_ypos(:,j,k) = max_r
2873 
2874  END DO y_interfaces_loop
2875 
2876  !$OMP END DO
2877 
2878  END IF
2879 
2880  !$OMP END PARALLEL
2881 
2882  RETURN
2883 
2884  END SUBROUTINE eval_speeds
2885 
2886 END MODULE solver_2d
subroutine eval_speeds
Characteristic speeds.
Definition: solver_2d.f90:2808
real(wp), dimension(:,:), allocatable sourcew_vect_x
Definition: geometry_2d.f90:43
real(wp), dimension(:,:,:,:), allocatable q_rk
Intermediate solutions of the Runge-Kutta scheme.
Definition: solver_2d.f90:148
real(wp), dimension(:,:,:), allocatable qp_cellnw
Reconstructed physical value at the NW corner of cell.
Definition: solver_2d.f90:76
integer n_rk
Runge-Kutta order.
real(wp), dimension(:,:), allocatable sourcew_vect_y
Definition: geometry_2d.f90:44
integer, dimension(:), allocatable j_stag_y
Definition: solver_2d.f90:177
real(wp), dimension(:,:,:), allocatable qp_interfacer
Reconstructed physical value at the right of the x-interface.
Definition: solver_2d.f90:60
integer, parameter sp
Definition: variables.f90:17
real(wp), dimension(:,:,:), allocatable a_interface_yneg
Local speeds at the bottom of the y-interface.
Definition: solver_2d.f90:99
real(wp), dimension(:,:), allocatable sources_vect_x
Definition: geometry_2d.f90:46
subroutine reconstruction(q_expl, qp_expl)
Linear reconstruction.
Definition: solver_2d.f90:2302
integer comp_cells_x
Number of control volumes x in the comp. domain.
Definition: geometry_2d.f90:64
real(wp) cell_size
Definition: geometry_2d.f90:68
subroutine eval_flux_gforce
Numerical fluxes GFORCE.
Definition: solver_2d.f90:2265
subroutine eval_local_speeds_x(qpj, vel_min, vel_max)
Local Characteristic speeds x direction.
real(wp) a_diag
Implicit coeff. for the non-hyp. part for a single step of the R-K scheme.
Definition: solver_2d.f90:145
real(wp) dy2
Half y Control volumes size.
Definition: geometry_2d.f90:63
real(wp), dimension(:,:,:), allocatable q_cellnw
Reconstructed value at the NW corner of cell.
Definition: solver_2d.f90:67
logical, dimension(:,:), allocatable mask11
Definition: solver_2d.f90:123
subroutine lnsrch(cell_fract_jk, dx_rel_jk, dy_rel_jk, qj_rel_NR_old, qj_org, qj_old, scal_f_old, grad_f, desc_dir, coeff_f, qj_rel, scal_f, right_term, stpmax, check, Rj_not_impl)
Search the descent stepsize.
Definition: solver_2d.f90:1506
real(wp), dimension(:,:,:), allocatable qp_interfacel
Reconstructed physical value at the left of the x-interface.
Definition: solver_2d.f90:58
real(wp), dimension(:,:,:), allocatable a_interface_x_max
Max local speeds at the x-interface.
Definition: solver_2d.f90:89
real(wp), dimension(:,:,:), allocatable q_cellne
Reconstructed value at the NE corner of cell.
Definition: solver_2d.f90:69
integer, dimension(:), allocatable k_cent
Definition: solver_2d.f90:172
real(wp), dimension(:,:,:), allocatable q_cellse
Reconstructed value at the SE corner of cell.
Definition: solver_2d.f90:73
subroutine average_kt(a1, a2, w1, w2, w_avg)
averaged KT flux
Definition: solver_2d.f90:2226
Parameters.
real(wp), dimension(:,:,:), allocatable a_interface_ypos
Local speeds at the top of the y-interface.
Definition: solver_2d.f90:101
subroutine qp_to_qp2(qpj, qp2j)
Additional Physical variables.
integer comp_cells_y
Number of control volumes y in the comp. domain.
Definition: geometry_2d.f90:66
Numerical solver.
Definition: solver_2d.f90:12
real(wp), dimension(:,:,:,:), allocatable nh
Intermediate non-hyperbolic terms of the Runge-Kutta scheme.
Definition: solver_2d.f90:157
subroutine deallocate_solver_variables
Memory deallocation.
Definition: solver_2d.f90:438
logical, dimension(:,:), allocatable sourcee
Definition: geometry_2d.f90:30
logical, dimension(:,:), allocatable sourcew
Definition: geometry_2d.f90:31
subroutine solve_rk_step(cell_fract_jk, dx_rel_jk, dy_rel_jk, qj, qj_old, a_tilde, a_dirk, a_diag, Rj_not_impl, divFluxj, NHj)
Runge-Kutta single step integration.
Definition: solver_2d.f90:1175
type(bc), dimension(:), allocatable bcw
bcW&flag defines the west boundary condition:
real(wp), dimension(:), allocatable omega_tilde
Coefficients for the explicit part of the Runge-Kutta scheme.
Definition: solver_2d.f90:133
real(wp), dimension(:,:,:), allocatable a_interface_y_max
Max local speeds at the y-interface.
Definition: solver_2d.f90:91
real(wp) x0
Left of the physical domain.
Definition: geometry_2d.f90:57
real(wp), dimension(:,:), allocatable cell_fract
Definition: geometry_2d.f90:74
real(wp), dimension(:,:,:), allocatable h_interface_y
Semidiscrete numerical interface fluxes.
Definition: solver_2d.f90:105
real(wp), dimension(:,:,:), allocatable q_mg_new
Definition: solver_2d.f90:181
real(wp), dimension(:,:,:,:), allocatable divflux
Intermediate hyperbolic terms of the Runge-Kutta scheme.
Definition: solver_2d.f90:154
real(wp), dimension(:,:), allocatable sourcee_vect_x
Definition: geometry_2d.f90:40
real(wp), dimension(:,:,:), allocatable q_cellsw
Reconstructed value at the SW corner of cell.
Definition: solver_2d.f90:71
real(wp), dimension(:,:,:), allocatable qp_cellne
Reconstructed physical value at the NE corner of cell.
Definition: solver_2d.f90:78
subroutine regrid_scalar(xin, yin, fin, xl, xr, yl, yr, fout)
Scalar regrid (2D)
integer, dimension(:), allocatable k_stag_x
Definition: solver_2d.f90:175
real(wp) function minmod(a, b)
integer n_vars
Number of conservative variables.
subroutine eval_flux_lxf
Numerical fluxes Lax-Friedrichs.
Definition: solver_2d.f90:2279
real(wp), dimension(:,:,:), allocatable q_interfacel
Reconstructed value at the left of the x-interface.
Definition: solver_2d.f90:49
integer comp_interfaces_y
Number of interfaces (comp_cells_y+1)
Definition: geometry_2d.f90:67
real(wp), dimension(:), allocatable x_comp
Location of the centers (x) of the control volume of the domain.
Definition: geometry_2d.f90:15
real(wp), dimension(:,:,:), allocatable qp
Physical variables ( )
Definition: solver_2d.f90:107
integer, parameter max_nl_iter
subroutine eval_fluxes(qcj, qpj, dir, flux)
Hyperbolic Fluxes.
subroutine eval_f(cell_fract_jk, dx_rel_jk, dy_rel_jk, qj, qj_old, a_diag, coeff_f, Rj_not_impl, f_nl, scal_f)
Evaluate the nonlinear system.
Definition: solver_2d.f90:1727
real(wp), dimension(:,:,:), allocatable q_fv
Solution of the finite-volume semidiscrete cheme.
Definition: solver_2d.f90:46
real(wp), dimension(:,:,:), allocatable q0
Conservative variables.
Definition: solver_2d.f90:44
integer comp_cells_xy
Definition: geometry_2d.f90:69
Constitutive equations.
logical normalize_q
Flag for the normalization of the array q in the implicit solution scheme.
Definition: solver_2d.f90:160
logical, dimension(:,:), allocatable mask21
Definition: solver_2d.f90:123
real(wp) dt
Time step.
Definition: solver_2d.f90:121
logical, dimension(:,:), allocatable solve_mask_y
Definition: solver_2d.f90:114
real(wp) cfl
Courant-Friedrichs-Lewy parameter.
real(wp), dimension(:,:), allocatable sourcee_vect_y
Definition: geometry_2d.f90:41
logical, dimension(:), allocatable implicit_flag
flag used for size of implicit non linear-system
real(wp), parameter tol_abs
subroutine limit(v, z, limiter, slope_lim)
Slope limiter.
real(wp), dimension(:), allocatable x_stag
Location of the boundaries (x) of the control volumes of the domain.
Definition: geometry_2d.f90:18
subroutine eval_source_bdry(time, vect_x, vect_y, source_bdry)
Internal boundary source fluxes.
real(wp), dimension(:,:,:), allocatable q_mg_old
Definition: solver_2d.f90:180
subroutine eval_local_speeds_y(qpj, vel_min, vel_max)
Local Characteristic speeds y direction.
character(len=20) solver_scheme
Finite volume method: .
real(wp), dimension(:,:,:), allocatable qp_interfacet
Reconstructed physical value at the top of the y-interface.
Definition: solver_2d.f90:64
real(wp) dx2
Half x Control volumes size.
Definition: geometry_2d.f90:62
integer, dimension(:,:), allocatable source_cell
Definition: geometry_2d.f90:29
real(wp), dimension(:,:), allocatable q1max
Maximum over time of thickness.
Definition: solver_2d.f90:86
Grid module.
Definition: geometry_2d.f90:7
subroutine deallocate_multigrid
Definition: solver_2d.f90:534
real(wp), dimension(:,:,:), allocatable q_interfacer
Reconstructed value at the right of the x-interface.
Definition: solver_2d.f90:51
real(wp), dimension(:,:,:), allocatable qp_cellse
Reconstructed physical value at the SE corner of cell.
Definition: solver_2d.f90:82
subroutine check_solve
Masking of cells to solve.
Definition: solver_2d.f90:598
real(wp), dimension(:), allocatable a_tilde
Explicit coeff. for the hyperbolic part for a single step of the R-K scheme.
Definition: solver_2d.f90:139
integer, dimension(:), allocatable k_stag_y
Definition: solver_2d.f90:178
real(wp), dimension(:), allocatable y_stag
Location of the boundaries (x) of the control volumes of the domain.
Definition: geometry_2d.f90:24
real(wp), dimension(:,:,:), allocatable q_interfacet
Reconstructed value at the top of the y-interface.
Definition: solver_2d.f90:55
logical, dimension(:,:), allocatable mask22
Definition: solver_2d.f90:123
subroutine eval_jacobian(cell_fract_jk, dx_rel_jk, dy_rel_jk, qj_rel, qj_org, coeff_f, left_matrix)
Evaluate the jacobian.
Definition: solver_2d.f90:1781
integer verbose_level
real(wp), dimension(:,:,:), allocatable a_interface_xneg
Local speeds at the left of the x-interface.
Definition: solver_2d.f90:95
real(wp), parameter tol_rel
subroutine timestep
Time-step computation.
Definition: solver_2d.f90:727
integer solve_interfaces_x
Definition: solver_2d.f90:117
subroutine qc_to_qp(qc, qp)
Conservative to physical variables.
integer, dimension(:), allocatable j_cent
Definition: solver_2d.f90:171
integer solve_interfaces_y
Definition: solver_2d.f90:118
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.
real(wp), dimension(:,:), allocatable dx_rel
Definition: geometry_2d.f90:75
real(wp), dimension(:,:), allocatable a_tilde_ij
Butcher Tableau for the explicit part of the Runge-Kutta scheme.
Definition: solver_2d.f90:128
real(wp), dimension(:,:,:), allocatable residual_term
Sum of all the terms of the equations except the transient term.
Definition: solver_2d.f90:169
real(wp), dimension(:,:,:), allocatable q_interfaceb
Reconstructed value at the bottom of the y-interface.
Definition: solver_2d.f90:53
real(wp) dx
Control volumes size.
Definition: geometry_2d.f90:56
logical opt_search_nl
Flag for the search of optimal step size in the implicit solution scheme.
Definition: solver_2d.f90:166
real(wp), dimension(:,:,:), allocatable qp_interfaceb
Reconstructed physical value at the bottom of the y-interface.
Definition: solver_2d.f90:62
real(wp), dimension(:,:,:), allocatable qp_cellsw
Reconstructed physical value at the SW corner of cell.
Definition: solver_2d.f90:80
logical normalize_f
Flag for the normalization of the array f in the implicit solution scheme.
Definition: solver_2d.f90:163
integer, dimension(10) limiter
Limiter for the slope in the linear reconstruction: .
real(wp), dimension(:,:), allocatable sources_vect_y
Definition: geometry_2d.f90:47
integer, parameter wp
working precision
Definition: variables.f90:21
type(bc), dimension(:), allocatable bcn
bcN&flag defines the north boundary condition:
real(wp), dimension(:,:), allocatable sourcen_vect_y
Definition: geometry_2d.f90:50
real(wp) t
time
Definition: solver_2d.f90:39
logical, dimension(:,:), allocatable sourcen
Definition: geometry_2d.f90:33
real(wp), dimension(:,:,:), allocatable h_interface_x
Semidiscrete numerical interface fluxes.
Definition: solver_2d.f90:103
integer n_eqns
Number of equations.
real(wp) max_dt
Largest time step allowed.
subroutine eval_flux_up
Upwind numerical fluxes.
Definition: solver_2d.f90:1960
real(wp), dimension(:,:,:), allocatable q
Conservative variables.
Definition: solver_2d.f90:42
subroutine imex_rk_solver
Runge-Kutta integration.
Definition: solver_2d.f90:868
type(bc), dimension(:), allocatable bcs
bcS&flag defines the south boundary condition:
logical, dimension(:,:), allocatable solve_mask
Definition: solver_2d.f90:112
subroutine eval_hyperbolic_terms(q_expl, qp_expl, divFlux_iRK)
Semidiscrete finite volume central scheme.
Definition: solver_2d.f90:1866
subroutine remap_solution
Definition: solver_2d.f90:541
real(wp), dimension(:,:,:,:), allocatable qp_rk
Intermediate physical solutions of the Runge-Kutta scheme.
Definition: solver_2d.f90:151
integer comp_interfaces_x
Number of interfaces (comp_cells_x+1)
Definition: geometry_2d.f90:65
real(wp), dimension(:,:,:), allocatable a_interface_xpos
Local speeds at the right of the x-interface.
Definition: solver_2d.f90:97
real(wp) y0
Bottom of the physical domain.
Definition: geometry_2d.f90:60
type(bc), dimension(:), allocatable bce
bcE&flag defines the east boundary condition:
subroutine qp_to_qc(qp, qc)
Physical to conservative variables.
logical, dimension(:,:), allocatable solve_mask_x
Definition: solver_2d.f90:113
real(wp), dimension(:,:), allocatable a_dirk_ij
Butcher Tableau for the implicit part of the Runge-Kutta scheme.
Definition: solver_2d.f90:130
integer, dimension(:), allocatable j_stag_x
Definition: solver_2d.f90:174
subroutine eval_flux_kt
Semidiscrete numerical fluxes.
Definition: solver_2d.f90:2077
integer solve_cells
Definition: solver_2d.f90:116
integer i_rk
loop counter for the RK iteration
Definition: solver_2d.f90:125
subroutine allocate_solver_variables
Memory allocation.
Definition: solver_2d.f90:199
real(wp) reconstr_coeff
Slope coefficient in the linear reconstruction.
real(wp), dimension(:), allocatable omega
Coefficients for the implicit part of the Runge-Kutta scheme.
Definition: solver_2d.f90:136
logical, dimension(:,:), allocatable mask12
Definition: solver_2d.f90:123
Global variables.
Definition: variables.f90:10
real(wp), dimension(:), allocatable a_dirk
Explicit coeff. for the non-hyp. part for a single step of the R-K scheme.
Definition: solver_2d.f90:142
real(wp), dimension(:), allocatable y_comp
Location of the centers (y) of the control volume of the domain.
Definition: geometry_2d.f90:21
integer n_nh
Number of non-hyperbolic terms.
real(wp), dimension(:,:), allocatable sourcen_vect_x
Definition: geometry_2d.f90:49
logical, dimension(:,:), allocatable sources
Definition: geometry_2d.f90:32
real(wp), dimension(:,:), allocatable source_xy
Array defining fraction of cells affected by source term.
Definition: solver_2d.f90:110
real(wp) dy
Control volumes size.
Definition: geometry_2d.f90:59
subroutine allocate_multigrid
Definition: solver_2d.f90:527
real(wp), dimension(:,:), allocatable dy_rel
Definition: geometry_2d.f90:76