7 use regrid_solvers,
only : solve_linear_system, solve_tridiagonal_system
10 implicit none ;
private 15 public bound_edge_values, average_discontinuous_edge_values, check_discontinuous_edge_values
16 public edge_values_explicit_h2, edge_values_explicit_h4
17 public edge_values_implicit_h4, edge_values_implicit_h6
18 public edge_slopes_implicit_h3, edge_slopes_implicit_h5
26 real,
parameter :: hneglect_edge_dflt = 1.e-10
28 real,
parameter :: hneglect_dflt = 1.e-30
30 real,
parameter :: hminfrac = 1.e-5
44 subroutine bound_edge_values( N, h, u, edge_val, h_neglect, answers_2018 )
45 integer,
intent(in) :: n
46 real,
dimension(N),
intent(in) :: h
47 real,
dimension(N),
intent(in) :: u
48 real,
dimension(N,2),
intent(inout) :: edge_val
50 real,
optional,
intent(in) :: h_neglect
51 logical,
optional,
intent(in) :: answers_2018
53 real :: sigma_l, sigma_c, sigma_r
56 logical :: use_2018_answers
57 integer :: k, km1, kp1
59 use_2018_answers = .true. ;
if (
present(answers_2018)) use_2018_answers = answers_2018
60 if (use_2018_answers)
then 61 hneglect = hneglect_dflt ;
if (
present(h_neglect)) hneglect = h_neglect
71 km1 = max(1,k-1) ; kp1 = min(k+1,n)
74 if (use_2018_answers)
then 75 sigma_l = 2.0 * ( u(k) - u(km1) ) / ( h(k) + hneglect )
76 sigma_c = 2.0 * ( u(kp1) - u(km1) ) / ( h(km1) + 2.0*h(k) + h(kp1) + hneglect )
77 sigma_r = 2.0 * ( u(kp1) - u(k) ) / ( h(k) + hneglect )
81 if ( (sigma_l * sigma_r) > 0.0 ) &
82 slope_x_h = 0.5 * h(k) * sign( min(abs(sigma_l),abs(sigma_c),abs(sigma_r)), sigma_c )
83 elseif ( ((h(km1) + h(kp1)) + 2.0*h(k)) > 0.0 )
then 84 sigma_l = ( u(k) - u(km1) )
85 sigma_c = ( u(kp1) - u(km1) ) * ( h(k) / ((h(km1) + h(kp1)) + 2.0*h(k)) )
86 sigma_r = ( u(kp1) - u(k) )
90 if ( (sigma_l * sigma_r) > 0.0 ) &
91 slope_x_h = sign( min(abs(sigma_l),abs(sigma_c),abs(sigma_r)), sigma_c )
95 if ( (u(km1)-edge_val(k,1)) * (edge_val(k,1)-u(k)) < 0.0 )
then 96 edge_val(k,1) = u(k) - sign( min( abs(slope_x_h), abs(edge_val(k,1)-u(k)) ), slope_x_h )
99 if ( (u(kp1)-edge_val(k,2)) * (edge_val(k,2)-u(k)) < 0.0 )
then 100 edge_val(k,2) = u(k) + sign( min( abs(slope_x_h), abs(edge_val(k,2)-u(k)) ), slope_x_h )
104 edge_val(k,1) = max( min( edge_val(k,1), max(u(km1), u(k)) ), min(u(km1), u(k)) )
105 edge_val(k,2) = max( min( edge_val(k,2), max(u(kp1), u(k)) ), min(u(kp1), u(k)) )
109 end subroutine bound_edge_values
115 subroutine average_discontinuous_edge_values( N, edge_val )
116 integer,
intent(in) :: n
117 real,
dimension(N,2),
intent(inout) :: edge_val
126 if ( edge_val(k,2) /= edge_val(k+1,1) )
then 127 u0_avg = 0.5 * ( edge_val(k,2) + edge_val(k+1,1) )
128 edge_val(k,2) = u0_avg
129 edge_val(k+1,1) = u0_avg
134 end subroutine average_discontinuous_edge_values
140 subroutine check_discontinuous_edge_values( N, u, edge_val )
141 integer,
intent(in) :: n
142 real,
dimension(N),
intent(in) :: u
143 real,
dimension(N,2),
intent(inout) :: edge_val
150 if ( (edge_val(k+1,1) - edge_val(k,2)) * (u(k+1) - u(k)) < 0.0 )
then 151 u0_avg = 0.5 * ( edge_val(k,2) + edge_val(k+1,1) )
152 u0_avg = max( min( u0_avg, max(u(k), u(k+1)) ), min(u(k), u(k+1)) )
153 edge_val(k,2) = u0_avg
154 edge_val(k+1,1) = u0_avg
158 end subroutine check_discontinuous_edge_values
174 subroutine edge_values_explicit_h2( N, h, u, edge_val )
175 integer,
intent(in) :: n
176 real,
dimension(N),
intent(in) :: h
177 real,
dimension(N),
intent(in) :: u
178 real,
dimension(N,2),
intent(inout) :: edge_val
190 if (h(k-1) + h(k) == 0.0)
then 191 edge_val(k,1) = 0.5 * (u(k-1) + u(k))
193 edge_val(k,1) = ( u(k-1)*h(k) + u(k)*h(k-1) ) / ( h(k-1) + h(k) )
197 edge_val(k-1,2) = edge_val(k,1)
200 end subroutine edge_values_explicit_h2
221 subroutine edge_values_explicit_h4( N, h, u, edge_val, h_neglect, answers_2018 )
222 integer,
intent(in) :: n
223 real,
dimension(N),
intent(in) :: h
224 real,
dimension(N),
intent(in) :: u
225 real,
dimension(N,2),
intent(inout) :: edge_val
227 real,
optional,
intent(in) :: h_neglect
228 logical,
optional,
intent(in) :: answers_2018
231 real :: h0, h1, h2, h3
235 real :: et1, et2, et3
237 real :: i_h012, i_h123
238 real :: i_den_et2, i_den_et3
239 real,
dimension(5) :: x
240 real,
dimension(4) :: dz
241 real,
dimension(4) :: u_tmp
242 real,
parameter :: c1_12 = 1.0 / 12.0
244 real,
dimension(4,4) :: a
245 real,
dimension(4) :: b, c
248 logical :: use_2018_answers
250 use_2018_answers = .true. ;
if (
present(answers_2018)) use_2018_answers = answers_2018
251 if (use_2018_answers)
then 252 hneglect = hneglect_edge_dflt ;
if (
present(h_neglect)) hneglect = h_neglect
254 hneglect = hneglect_dflt ;
if (
present(h_neglect)) hneglect = h_neglect
266 if (h0+h1==0.0 .or. h1+h2==0.0 .or. h2+h3==0.0)
then 267 if (use_2018_answers)
then 268 h_min = hminfrac*max( hneglect, h0+h1+h2+h3 )
270 h_min = hminfrac*max( hneglect, (h0+h1)+(h2+h3) )
272 h0 = max( h_min, h(i-2) )
273 h1 = max( h_min, h(i-1) )
274 h2 = max( h_min, h(i) )
275 h3 = max( h_min, h(i+1) )
278 if (use_2018_answers)
then 279 f1 = (h0+h1) * (h2+h3) / (h1+h2)
280 f2 = h2 * u(i-1) + h1 * u(i)
281 f3 = 1.0 / (h0+h1+h2) + 1.0 / (h1+h2+h3)
283 et2 = ( h2 * (h2+h3) / ( (h0+h1+h2)*(h0+h1) ) ) * &
284 ((h0+2.0*h1) * u(i-1) - h1 * u(i-2))
285 et3 = ( h1 * (h0+h1) / ( (h1+h2+h3)*(h2+h3) ) ) * &
286 ((2.0*h2+h3) * u(i) - h2 * u(i+1))
287 edge_val(i,1) = (et1 + et2 + et3) / ( h0 + h1 + h2 + h3)
289 i_h12 = 1.0 / (h1+h2)
290 i_den_et2 = 1.0 / ( ((h0+h1)+h2)*(h0+h1) ) ; i_h012 = (h0+h1) * i_den_et2
291 i_den_et3 = 1.0 / ( (h1+(h2+h3))*(h2+h3) ) ; i_h123 = (h2+h3) * i_den_et3
293 et1 = ( 1.0 + (h1 * i_h012 + (h0+h1) * i_h123) ) * i_h12 * (h2*(h2+h3)) * u(i-1) + &
294 ( 1.0 + (h2 * i_h123 + (h2+h3) * i_h012) ) * i_h12 * (h1*(h0+h1)) * u(i)
295 et2 = ( h1 * (h2*(h2+h3)) * i_den_et2 ) * (u(i-1)-u(i-2))
296 et3 = ( h2 * (h1*(h0+h1)) * i_den_et3 ) * (u(i) - u(i+1))
297 edge_val(i,1) = (et1 + (et2 + et3)) / ((h0 + h1) + (h2 + h3))
299 edge_val(i-1,2) = edge_val(i,1)
304 if (use_2018_answers)
then 305 h_min = max( hneglect, hminfrac*sum(h(1:4)) )
308 dx = max(h_min, h(i) )
310 do j = 1,4 ; a(i,j) = ( (x(i+1)**j) - (x(i)**j) ) / real(j) ;
enddo 314 call solve_linear_system( a, b, c, 4 )
317 edge_val(1,1) = evaluation_polynomial( c, 4, x(1) )
318 edge_val(1,2) = evaluation_polynomial( c, 4, x(2) )
320 do i=1,4 ; dz(i) = max(hneglect, h(i) ) ; u_tmp(i) = u(i) ;
enddo 321 call end_value_h4(dz, u_tmp, c)
325 edge_val(1,2) = c(1) + dz(1)*(c(2) + dz(1)*(c(3) + dz(1)*c(4)))
327 edge_val(2,1) = edge_val(1,2)
330 if (use_2018_answers)
then 331 h_min = max( hneglect, hminfrac*sum(h(n-3:n)) )
335 dx = max(h_min, h(n-4+i) )
337 do j = 1,4 ; a(i,j) = ( (x(i+1)**j) - (x(i)**j) ) / real(j) ;
enddo 341 call solve_linear_system( a, b, c, 4 )
344 edge_val(n,2) = evaluation_polynomial( c, 4, x(5) )
345 edge_val(n,1) = evaluation_polynomial( c, 4, x(4) )
349 do i=1,4 ; dz(i) = max(hneglect, h(n+1-i) ) ; u_tmp(i) = u(n+1-i) ;
enddo 350 call end_value_h4(dz, u_tmp, c)
354 edge_val(n,1) = c(1) + dz(1)*(c(2) + dz(1)*(c(3) + dz(1)*c(4)))
356 edge_val(n-1,2) = edge_val(n,1)
358 end subroutine edge_values_explicit_h4
386 subroutine edge_values_implicit_h4( N, h, u, edge_val, h_neglect, answers_2018 )
387 integer,
intent(in) :: n
388 real,
dimension(N),
intent(in) :: h
389 real,
dimension(N),
intent(in) :: u
390 real,
dimension(N,2),
intent(inout) :: edge_val
392 real,
optional,
intent(in) :: h_neglect
393 logical,
optional,
intent(in) :: answers_2018
400 real :: h0_2, h1_2, h0h1
401 real :: h0ph1_2, h0ph1_4
405 real,
dimension(5) :: x
406 real,
parameter :: c1_12 = 1.0 / 12.0
407 real,
parameter :: c1_3 = 1.0 / 3.0
408 real,
dimension(4) :: dz
409 real,
dimension(4) :: u_tmp
411 real,
dimension(4,4) :: asys
412 real,
dimension(4) :: bsys, csys
413 real,
dimension(N+1) :: tri_l, &
420 logical :: use_2018_answers
422 use_2018_answers = .true. ;
if (
present(answers_2018)) use_2018_answers = answers_2018
423 if (use_2018_answers)
then 424 hneglect = hneglect_edge_dflt ;
if (
present(h_neglect)) hneglect = h_neglect
426 hneglect = hneglect_dflt ;
if (
present(h_neglect)) hneglect = h_neglect
431 if (use_2018_answers)
then 442 h0ph1_2 = (h0 + h1)**2
449 alpha = h1_2 / h0ph1_2
450 beta = h0_2 / h0ph1_2
451 a = 2.0 * h1_2 * ( h1_2 + 2.0 * h0_2 + 3.0 * h0h1 ) / h0ph1_4
452 b = 2.0 * h0_2 * ( h0_2 + 2.0 * h1_2 + 3.0 * h0h1 ) / h0ph1_4
457 h0 = max(h(i), hneglect)
458 h1 = max(h(i+1), hneglect)
461 if (abs(h0) < 1.0e-12*abs(h1)) h0 = 1.0e-12*h1
462 if (abs(h1) < 1.0e-12*abs(h0)) h1 = 1.0e-12*h0
463 i_h2 = 1.0 / ((h0 + h1)**2)
464 alpha = (h1 * h1) * i_h2
465 beta = (h0 * h0) * i_h2
466 abmix = (h0 * h1) * i_h2
467 a = 2.0 * alpha * ( alpha + 2.0 * beta + 3.0 * abmix )
468 b = 2.0 * beta * ( beta + 2.0 * alpha + 3.0 * abmix )
470 tri_c(i+1) = 2.0*abmix
476 tri_b(i+1) = a * u(i) + b * u(i+1)
481 if (use_2018_answers)
then 482 h_min = max( hneglect, hminfrac*sum(h(1:4)) )
485 dx = max(h_min, h(i) )
487 do j = 1,4 ; asys(i,j) = ( (x(i+1)**j) - (x(i)**j) ) / j ;
enddo 491 call solve_linear_system( asys, bsys, csys, 4 )
493 tri_b(1) = evaluation_polynomial( csys, 4, x(1) )
496 do i=1,4 ; dz(i) = max(hneglect, h(i) ) ; u_tmp(i) = u(i) ;
enddo 497 call end_value_h4(dz, u_tmp, csys)
505 if (use_2018_answers)
then 506 h_min = max( hneglect, hminfrac*sum(h(n-3:n)) )
509 dx = max(h_min, h(n-4+i) )
511 do j = 1,4 ; asys(i,j) = ( (x(i+1)**j) - (x(i)**j) ) / j ;
enddo 512 bsys(i) = u(n-4+i) * dx
515 call solve_linear_system( asys, bsys, csys, 4 )
518 tri_b(n+1) = evaluation_polynomial( csys, 4, x(5) )
524 do i=1,4 ; dz(i) = max(hneglect, h(n+1-i) ) ; u_tmp(i) = u(n+1-i) ;
enddo 525 call end_value_h4(dz, u_tmp, csys)
533 if (use_2018_answers)
then 534 call solve_tridiagonal_system( tri_l, tri_d, tri_u, tri_b, tri_x, n+1 )
536 call solve_diag_dominant_tridiag( tri_l, tri_c, tri_u, tri_b, tri_x, n+1 )
539 edge_val(1,1) = tri_x(1)
541 edge_val(i,1) = tri_x(i)
542 edge_val(i-1,2) = tri_x(i)
544 edge_val(n,2) = tri_x(n+1)
546 end subroutine edge_values_implicit_h4
550 subroutine end_value_h4(dz, u, Csys)
551 real,
dimension(4),
intent(in) :: dz
553 real,
dimension(4),
intent(in) :: u
554 real,
dimension(4),
intent(out) :: Csys
560 real :: h1, h2, h3, h4
561 real :: h12, h23, h34
565 real :: I_h12, I_h23, I_h34
566 real :: I_h123, I_h234
570 real :: min_frac = 1.0e-6
571 real,
parameter :: C1_3 = 1.0 / 3.0
591 h1 = dz(1) ; h2 = dz(2) ; h3 = dz(3) ; h4 = dz(4)
595 if ((h2+h3) < min_frac*h1) h3 = min_frac*h1 - h2
596 if ((h3+h4) < min_frac*h1) h4 = min_frac*h1 - h3
598 h12 = h1+h2 ; h23 = h2+h3 ; h34 = h3+h4
599 h123 = h12 + h3 ; h234 = h2 + h34 ; h1234 = h12 + h34
601 i_denb3 = 1.0 / (h123 * h12 * h23)
602 i_h12 = (h123 * h23) * i_denb3
603 i_h23 = (h12 * h123) * i_denb3
604 i_h123 = (h12 * h23) * i_denb3
605 i_denom = 1.0 / ( h1234 * (h234 * h34) )
606 i_h34 = (h1234 * h234) * i_denom
607 i_h234 = (h1234 * h34) * i_denom
608 i_h1234 = (h234 * h34) * i_denom
627 wt(1,1) = -h1 * (i_h1234 + i_h123 + i_h12)
628 wt(2,1) = h1 * h12 * ( i_h234 * i_h1234 + i_h23 * (i_h234 + i_h123) )
629 wt(3,1) = -h1 * h12 * h123 * i_denom
631 wt(1,2) = 2.0 * (i_h12*(1.0 + (h1+h12) * (i_h1234 + i_h123)) + h1 * i_h1234*i_h123)
632 wt(2,2) = -2.0 * ((h1 * h12 * i_h1234) * (i_h23 * (i_h234 + i_h123)) + &
633 (h1+h12) * ( i_h1234*i_h234 + i_h23 * (i_h234 + i_h123) ) )
634 wt(3,2) = 2.0 * ((h1+h12) * h123 + h1*h12 ) * i_denom
636 wt(1,3) = -3.0 * i_h12 * i_h123* ( 1.0 + i_h1234 * ((h1+h12)+h123) )
637 wt(2,3) = 3.0 * i_h23 * ( i_h123 + i_h1234 * ((h1+h12)+h123) * (i_h123 + i_h234) )
638 wt(3,3) = -3.0 * ((h1+h12)+h123) * i_denom
640 wt(1,4) = 4.0 * i_h1234 * i_h123 * i_h12
641 wt(2,4) = -4.0 * i_h1234 * (i_h23 * (i_h123 + i_h234))
642 wt(3,4) = 4.0 * i_denom
644 csys(1) = ((u(1) + wt(1,1) * (u(2)-u(1))) + wt(2,1) * (u(3)-u(2))) + wt(3,1) * (u(4)-u(3))
645 csys(2) = (wt(1,2) * (u(2)-u(1)) + wt(2,2) * (u(3)-u(2))) + wt(3,2) * (u(4)-u(3))
646 csys(3) = (wt(1,3) * (u(2)-u(1)) + wt(2,3) * (u(3)-u(2))) + wt(3,3) * (u(4)-u(3))
647 csys(4) = (wt(1,4) * (u(2)-u(1)) + wt(2,4) * (u(3)-u(2))) + wt(3,4) * (u(4)-u(3))
664 end subroutine end_value_h4
696 subroutine edge_slopes_implicit_h3( N, h, u, edge_slopes, h_neglect, answers_2018 )
697 integer,
intent(in) :: n
698 real,
dimension(N),
intent(in) :: h
699 real,
dimension(N),
intent(in) :: u
700 real,
dimension(N,2),
intent(inout) :: edge_slopes
702 real,
optional,
intent(in) :: h_neglect
703 logical,
optional,
intent(in) :: answers_2018
707 real :: h0_2, h1_2, h0h1
715 real,
parameter :: c1_12 = 1.0 / 12.0
716 real,
dimension(4) :: dz
717 real,
dimension(4) :: u_tmp
718 real,
dimension(5) :: x
720 real,
dimension(4,4) :: asys
721 real,
dimension(4) :: bsys, csys
722 real,
dimension(3) :: dsys
723 real,
dimension(N+1) :: tri_l, &
731 logical :: use_2018_answers
733 hneglect = hneglect_dflt ;
if (
present(h_neglect)) hneglect = h_neglect
734 hneglect3 = hneglect**3
735 use_2018_answers = .true. ;
if (
present(answers_2018)) use_2018_answers = answers_2018
740 if (use_2018_answers)
then 752 d = 4.0 * h0h1 * ( h0 + h1 ) + h1_3 + h0_3
755 alpha = h1 * (h0_2 + h0h1 - h1_2) / ( d + hneglect3 )
756 beta = h0 * (h1_2 + h0h1 - h0_2) / ( d + hneglect3 )
757 a = -12.0 * h0h1 / ( d + hneglect3 )
764 tri_b(i+1) = a * u(i) + b * u(i+1)
767 h0 = max(h(i), hneglect)
768 h1 = max(h(i+1), hneglect)
770 i_h = 1.0 / (h0 + h1)
771 h0 = h0 * i_h ; h1 = h1 * i_h
773 h0h1 = h0 * h1 ; h0_2 = h0 * h0 ; h1_2 = h1 * h1
774 h0_3 = h0_2 * h0 ; h1_3 = h1_2 * h1
777 i_d = 1.0 / (4.0 * h0h1 * ( h0 + h1 ) + h1_3 + h0_3)
778 tri_l(i+1) = (h1 * ((h0_2 + h0h1) - h1_2)) * i_d
780 tri_c(i+1) = 2.0 * ((h0_2 + h1_2) * (h0 + h1)) * i_d
781 tri_u(i+1) = (h0 * ((h1_2 + h0h1) - h0_2)) * i_d
788 tri_b(i+1) = 12.0 * (h0h1 * i_d) * ((u(i+1) - u(i)) * i_h)
794 if (use_2018_answers)
then 799 do j = 1,4 ; asys(i,j) = ( (x(i+1)**j) - (x(i)**j) ) / j ;
enddo 803 call solve_linear_system( asys, bsys, csys, 4 )
805 dsys(1) = csys(2) ; dsys(2) = 2.0 * csys(3) ; dsys(3) = 3.0 * csys(4)
806 tri_b(1) = evaluation_polynomial( dsys, 3, x(1) )
809 do i=1,4 ; dz(i) = max(hneglect, h(i) ) ; u_tmp(i) = u(i) ;
enddo 810 call end_value_h4(dz, u_tmp, csys)
819 if (use_2018_answers)
then 824 do j = 1,4 ; asys(i,j) = ( (x(i+1)**j) - (x(i)**j) ) / j ;
enddo 825 bsys(i) = u(n-4+i) * dx
828 call solve_linear_system( asys, bsys, csys, 4 )
830 dsys(1) = csys(2) ; dsys(2) = 2.0 * csys(3) ; dsys(3) = 3.0 * csys(4)
832 tri_b(n+1) = evaluation_polynomial( dsys, 3, x(5) )
837 do i=1,4 ; dz(i) = max(hneglect, h(n+1-i) ) ; u_tmp(i) = u(n+1-i) ;
enddo 839 call end_value_h4(dz, u_tmp, csys)
842 tri_b(n+1) = -csys(2)
848 if (use_2018_answers)
then 849 call solve_tridiagonal_system( tri_l, tri_d, tri_u, tri_b, tri_x, n+1 )
851 call solve_diag_dominant_tridiag( tri_l, tri_c, tri_u, tri_b, tri_x, n+1 )
855 edge_slopes(i,1) = tri_x(i)
856 edge_slopes(i-1,2) = tri_x(i)
858 edge_slopes(1,1) = tri_x(1)
859 edge_slopes(n,2) = tri_x(n+1)
861 end subroutine edge_slopes_implicit_h3
866 subroutine edge_slopes_implicit_h5( N, h, u, edge_slopes, h_neglect, answers_2018 )
867 integer,
intent(in) :: n
868 real,
dimension(N),
intent(in) :: h
869 real,
dimension(N),
intent(in) :: u
870 real,
dimension(N,2),
intent(inout) :: edge_slopes
872 real,
optional,
intent(in) :: h_neglect
873 logical,
optional,
intent(in) :: answers_2018
908 real :: h0, h1, h2, h3
918 real,
dimension(7) :: x
919 real,
parameter :: c1_12 = 1.0 / 12.0
920 real,
parameter :: c5_6 = 5.0 / 6.0
922 real,
dimension(6,6) :: asys
923 real,
dimension(6) :: bsys, csys
924 real,
dimension(N+1) :: tri_l, &
929 real :: h_min_frac = 1.0e-4
932 hneglect = hneglect_dflt ;
if (
present(h_neglect)) hneglect = h_neglect
937 hmin = max(hneglect, h_min_frac*((h(k-1) + h(k)) + (h(k+1) + h(k+2))))
938 h0 = max(h(k-1), hmin) ; h1 = max(h(k), hmin)
939 h2 = max(h(k+1), hmin) ; h3 = max(h(k+2), hmin)
942 h1_2 = h1 * h1 ; h1_3 = h1_2 * h1 ; h1_4 = h1_2 * h1_2 ; h1_5 = h1_3 * h1_2
943 h2_2 = h2 * h2 ; h2_3 = h2_2 * h2 ; h2_4 = h2_2 * h2_2 ; h2_5 = h2_3 * h2_2
949 asys(1:6,1) = (/ 0.0, 0.0, 1.0, 1.0, 1.0, 1.0 /)
950 asys(1:6,2) = (/ 2.0, 2.0, (2.0*h1 + h0), h1, -h2, -(2.0*h2 + h3) /)
951 asys(1:6,3) = (/ 6.0*h1, -6.0* h2, (3.0*h1_2 + h0*(3.0*h1 + h0)), &
952 h1_2, h2_2, (3.0*h2_2 + h3*(3.0*h2 + h3)) /)
953 asys(1:6,4) = (/ -12.0*h1_2, -12.0*h2_2, -(4.0*h1_3 + h0*(6.0*h1_2 + h0*(4.0*h1 + h0))), &
954 -h1_3, h2_3, (4.0*h2_3 + h3*(6.0*h2_2 + h3*(4.0*h2 + h3))) /)
955 asys(1:6,5) = (/ 20.0*h1_3, -20.0*h2_3, (5.0*h1_4 + h0*(10.0*h1_3 + h0*(10.0*h1_2 + h0*(5.0*h1 + h0)))), &
956 h1_4, h2_4, (5.0*h2_4 + h3*(10.0*h2_3 + h3*(10.0*h2_2 + h3*(5.0*h2 + h3)))) /)
957 asys(1:6,6) = (/ -30.0*h1_4, -30.0*h2_4, &
958 -(6.0*h1_5 + h0*(15.0*h1_4 + h0*(20.0*h1_3 + h0*(15.0*h1_2 + h0*(6.0*h1 + h0))))), &
960 (6.0*h2_5 + h3*(15.0*h2_4 + h3*(20.0*h2_3 + h3*(15.0*h2_2 + h3*(6.0*h2 + h3))))) /)
961 bsys(1:6) = (/ 0.0, -2.0, 0.0, 0.0, 0.0, 0.0 /)
963 call linear_solver( 6, asys, bsys, csys )
971 tri_b(k+1) = csys(3) * u(k-1) + csys(4) * u(k) + csys(5) * u(k+1) + csys(6) * u(k+2)
978 hmin = max(hneglect, h_min_frac*((h(1) + h(2)) + (h(3) + h(4))))
979 h0 = max(h(1), hmin) ; h1 = max(h(2), hmin)
980 h2 = max(h(3), hmin) ; h3 = max(h(4), hmin)
983 h1_2 = h1 * h1 ; h1_3 = h1_2 * h1 ; h1_4 = h1_2 * h1_2 ; h1_5 = h1_3 * h1_2
984 h2_2 = h2 * h2 ; h2_3 = h2_2 * h2 ; h2_4 = h2_2 * h2_2 ; h2_5 = h2_3 * h2_2
985 h01 = h0 + h1 ; h01_2 = h01 * h01
988 asys(1:6,1) = (/ 0.0, 0.0, 1.0, 1.0, 1.0, 1.0 /)
989 asys(1:6,2) = (/ 2.0, 2.0, (2.0*h1 + h0), h1, -h2, -(2.0*h2 + h3) /)
990 asys(1:6,3) = (/ 6.0*h01, 0.0, (3.0*h1_2 + h0*(3.0*h1 + h0)), &
991 h1_2, h2_2, (3.0*h2_2 + h3*(3.0*h2 + h3)) /)
992 asys(1:6,4) = (/ -12.0*h01_2, 0.0, -(4.0*h1_3 + h0*(6.0*h1_2 + h0*(4.0*h1 + h0))), &
993 -h1_3, h2_3, (4.0*h2_3 + h3*(6.0*h2_2 + h3*(4.0*h2 + h3))) /)
994 asys(1:6,5) = (/ 20.0*(h01*h01_2), 0.0, (5.0*h1_4 + h0*(10.0*h1_3 + h0*(10.0*h1_2 + h0*(5.0*h1 + h0)))), &
995 h1_4, h2_4, (5.0*h2_4 + h3*(10.0*h2_3 + h3*(10.0*h2_2 + h3*(5.0*h2 + h3)))) /)
996 asys(1:6,6) = (/ -30.0*(h01_2*h01_2), 0.0, &
997 -(6.0*h1_5 + h0*(15.0*h1_4 + h0*(20.0*h1_3 + h0*(15.0*h1_2 + h0*(6.0*h1 + h0))))), &
999 (6.0*h2_5 + h3*(15.0*h2_4 + h3*(20.0*h2_3 + h3*(15.0*h2_2 + h3*(6.0*h2 + h3))))) /)
1000 bsys(1:6) = (/ 0.0, -2.0, -6.0*h1, 12.0*h1_2, -20.0*h1_3, 30.0*h1_4 /)
1002 call linear_solver( 6, asys, bsys, csys )
1010 tri_b(2) = csys(3) * u(1) + csys(4) * u(2) + csys(5) * u(3) + csys(6) * u(4)
1016 xavg = x(i) + 0.5 * dx
1017 asys(1:6,i) = (/ 1.0, xavg, (xavg**2 + c1_12*dx**2), xavg * (xavg**2 + 0.25*dx**2), &
1018 (xavg**4 + 0.5*xavg**2*dx**2 + 0.0125*dx**4), &
1019 xavg * (xavg**4 + c5_6*xavg**2*dx**2 + 0.0625*dx**4) /)
1024 call linear_solver( 6, asys, bsys, csys )
1034 hmin = max(hneglect, h_min_frac*((h(n-3) + h(n-2)) + (h(n-1) + h(n))))
1035 h0 = max(h(n-3), hmin) ; h1 = max(h(n-2), hmin)
1036 h2 = max(h(n-1), hmin) ; h3 = max(h(n), hmin)
1039 h1_2 = h1 * h1 ; h1_3 = h1_2 * h1 ; h1_4 = h1_2 * h1_2 ; h1_5 = h1_3 * h1_2
1040 h2_2 = h2 * h2 ; h2_3 = h2_2 * h2 ; h2_4 = h2_2 * h2_2 ; h2_5 = h2_3 * h2_2
1042 h23 = h2 + h3 ; h23_2 = h23 * h23
1045 asys(1:6,1) = (/ 0.0, 0.0, 1.0, 1.0, 1.0, 1.0 /)
1046 asys(1:6,2) = (/ 2.0, 2.0, (2.0*h1 + h0), h1, -h2, -(2.0*h2 + h3) /)
1047 asys(1:6,3) = (/ 0.0, -6.0*h23, (3.0*h1_2 + h0*(3.0*h1 + h0)), &
1048 h1_2, h2_2, (3.0*h2_2 + h3*(3.0*h2 + h3)) /)
1049 asys(1:6,4) = (/ 0.0, -12.0*h23_2, -(4.0*h1_3 + h0*(6.0*h1_2 + h0*(4.0*h1 + h0))), &
1050 -h1_3, h2_3, (4.0*h2_3 + h3*(6.0*h2_2 + h3*(4.0*h2 + h3))) /)
1051 asys(1:6,5) = (/ 0.0, -20.0*(h23*h23_2), (5.0*h1_4 + h0*(10.0*h1_3 + h0*(10.0*h1_2 + h0*(5.0*h1 + h0)))), &
1052 h1_4, h2_4, (5.0*h2_4 + h3*(10.0*h2_3 + h3*(10.0*h2_2 + h3*(5.0*h2 + h3)))) /)
1053 asys(1:6,6) = (/ 0.0, -30.0*(h23_2*h23_2), &
1054 -(6.0*h1_5 + h0*(15.0*h1_4 + h0*(20.0*h1_3 + h0*(15.0*h1_2 + h0*(6.0*h1 + h0))))), &
1056 (6.0*h2_5 + h3*(15.0*h2_4 + h3*(20.0*h2_3 + h3*(15.0*h2_2 + h3*(6.0*h2 + h3))))) /)
1057 bsys(1:6) = (/ 0.0, -2.0, 6.0*h2, 12.0*h2_2, 20.0*h2_3, 30.0*h2_4 /)
1059 call linear_solver( 6, asys, bsys, csys )
1067 tri_b(n) = csys(3) * u(n-3) + csys(4) * u(n-2) + csys(5) * u(n-1) + csys(6) * u(n)
1073 xavg = x(i) + 0.5*dx
1074 asys(1:6,i) = (/ 1.0, xavg, (xavg**2 + c1_12*dx**2), xavg * (xavg**2 + 0.25*dx**2), &
1075 (xavg**4 + 0.5*xavg**2*dx**2 + 0.0125*dx**4), &
1076 xavg * (xavg**4 + c5_6*xavg**2*dx**2 + 0.0625*dx**4) /)
1081 call linear_solver( 6, asys, bsys, csys )
1086 tri_b(n+1) = -csys(2)
1089 call solve_tridiagonal_system( tri_l, tri_d, tri_u, tri_b, tri_x, n+1 )
1092 edge_slopes(i,1) = tri_x(i)
1093 edge_slopes(i-1,2) = tri_x(i)
1095 edge_slopes(1,1) = tri_x(1)
1096 edge_slopes(n,2) = tri_x(n+1)
1098 end subroutine edge_slopes_implicit_h5
1136 subroutine edge_values_implicit_h6( N, h, u, edge_val, h_neglect, answers_2018 )
1137 integer,
intent(in) :: n
1138 real,
dimension(N),
intent(in) :: h
1139 real,
dimension(N),
intent(in) :: u
1140 real,
dimension(N,2),
intent(inout) :: edge_val
1142 real,
optional,
intent(in) :: h_neglect
1143 logical,
optional,
intent(in) :: answers_2018
1146 real :: h0, h1, h2, h3
1148 real :: h01, h01_2, h01_3
1149 real :: h23, h23_2, h23_3
1151 real :: h1_2, h2_2, h1_3, h2_3
1152 real :: h1_4, h2_4, h1_5, h2_5
1154 real,
dimension(7) :: x
1155 real,
parameter :: c1_12 = 1.0 / 12.0
1156 real,
parameter :: c5_6 = 5.0 / 6.0
1158 real,
dimension(6,6) :: asys
1159 real,
dimension(6) :: bsys, csys
1160 real,
dimension(N+1) :: tri_l, &
1167 hneglect = hneglect_edge_dflt ;
if (
present(h_neglect)) hneglect = h_neglect
1172 hmin = max(hneglect, hminfrac*((h(k-1) + h(k)) + (h(k+1) + h(k+2))))
1173 h0 = max(h(k-1), hmin) ; h1 = max(h(k), hmin)
1174 h2 = max(h(k+1), hmin) ; h3 = max(h(k+2), hmin)
1177 h1_2 = h1 * h1 ; h1_3 = h1_2 * h1 ; h1_4 = h1_2 * h1_2 ; h1_5 = h1_3 * h1_2
1178 h2_2 = h2 * h2 ; h2_3 = h2_2 * h2 ; h2_4 = h2_2 * h2_2 ; h2_5 = h2_3 * h2_2
1181 asys(1:6,1) = (/ 1.0, 1.0, -1.0, -1.0, -1.0, -1.0 /)
1182 asys(1:6,2) = (/ -2.0*h1, 2.0*h2, (2.0*h1 + h0), h1, -h2, -(2.0*h2 + h3) /)
1183 asys(1:6,3) = (/ 3.0*h1_2, 3.0*h2_2, -(3.0*h1_2 + h0*(3.0*h1 + h0)), &
1184 -h1_2, -h2_2, -(3.0*h2_2 + h3*(3.0*h2 + h3)) /)
1185 asys(1:6,4) = (/ -4.0*h1_3, 4.0*h2_3, (4.0*h1_3 + h0*(6.0*h1_2 + h0*(4.0*h1 + h0))), &
1186 h1_3, -h2_3, -(4.0*h2_3 + h3*(6.0*h2_2 + h3*(4.0*h2 + h3))) /)
1187 asys(1:6,5) = (/ 5.0*h1_4, 5.0*h2_4, -(5.0*h1_4 + h0*(10.0*h1_3 + h0*(10.0*h1_2 + h0*(5.0*h1 + h0)))), &
1188 -h1_4, -h2_4, -(5.0*h2_4 + h3*(10.0*h2_3 + h3*(10.0*h2_2 + h3*(5.0*h2 + h3)))) /)
1189 asys(1:6,6) = (/ -6.0*h1_5, 6.0*h2_5, &
1190 (6.0*h1_5 + h0*(15.0*h1_4 + h0*(20.0*h1_3 + h0*(15.0*h1_2 + h0*(6.0*h1 + h0))))), &
1192 -(6.0*h2_5 + h3*(15.0*h2_4 + h3*(20.0*h2_3 + h3*(15.0*h2_2 + h3*(6.0*h2 + h3))))) /)
1193 bsys(1:6) = (/ -1.0, 0.0, 0.0, 0.0, 0.0, 0.0 /)
1195 call linear_solver( 6, asys, bsys, csys )
1203 tri_b(k+1) = csys(3) * u(k-1) + csys(4) * u(k) + csys(5) * u(k+1) + csys(6) * u(k+2)
1210 hmin = max(hneglect, hminfrac*((h(1) + h(2)) + (h(3) + h(4))))
1211 h0 = max(h(1), hmin) ; h1 = max(h(2), hmin)
1212 h2 = max(h(3), hmin) ; h3 = max(h(4), hmin)
1215 h1_2 = h1 * h1 ; h1_3 = h1_2 * h1 ; h1_4 = h1_2 * h1_2 ; h1_5 = h1_3 * h1_2
1216 h2_2 = h2 * h2 ; h2_3 = h2_2 * h2 ; h2_4 = h2_2 * h2_2 ; h2_5 = h2_3 * h2_2
1217 h01 = h0 + h1 ; h01_2 = h01 * h01 ; h01_3 = h01 * h01_2
1220 asys(1:6,1) = (/ 1.0, 1.0, -1.0, -1.0, -1.0, -1.0 /)
1221 asys(1:6,2) = (/ -2.0*h01, 0.0, (2.0*h1 + h0), h1, -h2, -(2.0*h2 + h3) /)
1222 asys(1:6,3) = (/ 3.0*h01_2, 0.0, -(3.0*h1_2 + h0*(3.0*h1 + h0)), &
1223 -h1_2, -h2_2, -(3.0*h2_2 + h3*(3.0*h2 + h3)) /)
1224 asys(1:6,4) = (/ -4.0*h01_3, 0.0, (4.0*h1_3 + h0*(6.0*h1_2 + h0*(4.0*h1 + h0))), &
1225 h1_3, -h2_3, -(4.0*h2_3 + h3*(6.0*h2_2 + h3*(4.0*h2 + h3))) /)
1226 asys(1:6,5) = (/ 5.0*(h01_2*h01_2), 0.0, -(5.0*h1_4 + h0*(10.0*h1_3 + h0*(10.0*h1_2 + h0*(5.0*h1 + h0)))), &
1227 -h1_4, -h2_4, -(5.0*h2_4 + h3*(10.0*h2_3 + h3*(10.0*h2_2 + h3*(5.0*h2 + h3)))) /)
1228 asys(1:6,6) = (/ -6.0*(h01_3*h01_2), 0.0, &
1229 (6.0*h1_5 + h0*(15.0*h1_4 + h0*(20.0*h1_3 + h0*(15.0*h1_2 + h0*(6.0*h1 + h0))))), &
1231 -(6.0*h2_5 + h3*(15.0*h2_4 + h3*(20.0*h2_3 + h3*(15.0*h2_2 + h3*(6.0*h2 + h3))))) /)
1232 bsys(1:6) = (/ -1.0, 2.0*h1, -3.0*h1_2, 4.0*h1_3, -5.0*h1_4, 6.0*h1_5 /)
1234 call linear_solver( 6, asys, bsys, csys )
1242 tri_b(2) = csys(3) * u(1) + csys(4) * u(2) + csys(5) * u(3) + csys(6) * u(4)
1245 hmin = max( hneglect, hminfrac*((h(1)+h(2)) + (h(5)+h(6)) + (h(3)+h(4))) )
1248 dx = max( hmin, h(i) )
1249 xavg = x(i) + 0.5*dx
1250 asys(1:6,i) = (/ 1.0, xavg, (xavg**2 + c1_12*dx**2), xavg * (xavg**2 + 0.25*dx**2), &
1251 (xavg**4 + 0.5*xavg**2*dx**2 + 0.0125*dx**4), &
1252 xavg * (xavg**4 + c5_6*xavg**2*dx**2 + 0.0625*dx**4) /)
1257 call linear_solver( 6, asys, bsys, csys )
1262 tri_b(1) = evaluation_polynomial( csys, 6, x(1) )
1267 hmin = max(hneglect, hminfrac*((h(n-3) + h(n-2)) + (h(n-1) + h(n))))
1268 h0 = max(h(n-3), hmin) ; h1 = max(h(n-2), hmin)
1269 h2 = max(h(n-1), hmin) ; h3 = max(h(n), hmin)
1272 h1_2 = h1 * h1 ; h1_3 = h1_2 * h1 ; h1_4 = h1_2 * h1_2 ; h1_5 = h1_3 * h1_2
1273 h2_2 = h2 * h2 ; h2_3 = h2_2 * h2 ; h2_4 = h2_2 * h2_2 ; h2_5 = h2_3 * h2_2
1274 h23 = h2 + h3 ; h23_2 = h23 * h23 ; h23_3 = h23 * h23_2
1277 asys(1:6,1) = (/ 1.0, 1.0, -1.0, -1.0, -1.0, -1.0 /)
1278 asys(1:6,2) = (/ 0.0, 2.0*h23, (2.0*h1 + h0), h1, -h2, -(2.0*h2 + h3) /)
1279 asys(1:6,3) = (/ 0.0, 3.0*h23_2, -(3.0*h1_2 + h0*(3.0*h1 + h0)), &
1280 -h1_2, -h2_2, -(3.0*h2_2 + h3*(3.0*h2 + h3)) /)
1281 asys(1:6,4) = (/ 0.0, 4.0*h23_3, (4.0*h1_3 + h0*(6.0*h1_2 + h0*(4.0*h1 + h0))), &
1282 h1_3, -h2_3, -(4.0*h2_3 + h3*(6.0*h2_2 + h3*(4.0*h2 + h3))) /)
1283 asys(1:6,5) = (/ 0.0, 5.0*(h23_2*h23_2), -(5.0*h1_4 + h0*(10.0*h1_3 + h0*(10.0*h1_2 + h0*(5.0*h1 + h0)))), &
1284 -h1_4, -h2_4, -(5.0*h2_4 + h3*(10.0*h2_3 + h3*(10.0*h2_2 + h3*(5.0*h2 + h3)))) /)
1285 asys(1:6,6) = (/ 0.0, 6.0*(h23_3*h23_2), &
1286 (6.0*h1_5 + h0*(15.0*h1_4 + h0*(20.0*h1_3 + h0*(15.0*h1_2 + h0*(6.0*h1 + h0))))), &
1288 -(6.0*h2_5 + h3*(15.0*h2_4 + h3*(20.0*h2_3 + h3*(15.0*h2_2 + h3*(6.0*h2 + h3))))) /)
1289 bsys(1:6) = (/ -1.0, -2.0*h2, -3.0*h2_2, -4.0*h2_3, -5.0*h2_4, -6.0*h2_5 /)
1291 call linear_solver( 6, asys, bsys, csys )
1299 tri_b(n) = csys(3) * u(n-3) + csys(4) * u(n-2) + csys(5) * u(n-1) + csys(6) * u(n)
1302 hmin = max( hneglect, hminfrac*(h(n-3) + h(n-2)) + ((h(n-1) + h(n)) + (h(n-5) + h(n-4))) )
1305 dx = max( hmin, h(n+1-i) )
1306 xavg = x(i) + 0.5 * dx
1307 asys(1:6,i) = (/ 1.0, xavg, (xavg**2 + c1_12*dx**2), xavg * (xavg**2 + 0.25*dx**2), &
1308 (xavg**4 + 0.5*xavg**2*dx**2 + 0.0125*dx**4), &
1309 xavg * (xavg**4 + c5_6*xavg**2*dx**2 + 0.0625*dx**4) /)
1314 call linear_solver( 6, asys, bsys, csys )
1319 tri_b(n+1) = csys(1)
1322 call solve_tridiagonal_system( tri_l, tri_d, tri_u, tri_b, tri_x, n+1 )
1325 edge_val(i,1) = tri_x(i)
1326 edge_val(i-1,2) = tri_x(i)
1328 edge_val(1,1) = tri_x(1)
1329 edge_val(n,2) = tri_x(n+1)
1331 end subroutine edge_values_implicit_h6
1341 subroutine solve_diag_dominant_tridiag( Al, Ac, Au, R, X, N )
1342 integer,
intent(in) :: N
1343 real,
dimension(N),
intent(in) :: Ac
1344 real,
dimension(N),
intent(in) :: Al
1345 real,
dimension(N),
intent(in) :: Au
1346 real,
dimension(N),
intent(in) :: R
1347 real,
dimension(N),
intent(out) :: X
1349 real,
dimension(N) :: c1
1357 i_pivot = 1.0 / (ac(1) + au(1))
1358 d1 = ac(1) * i_pivot
1359 c1(1) = au(1) * i_pivot
1360 x(1) = r(1) * i_pivot
1362 denom_t1 = ac(k) + d1 * al(k)
1363 i_pivot = 1.0 / (denom_t1 + au(k))
1364 d1 = denom_t1 * i_pivot
1365 c1(k) = au(k) * i_pivot
1366 x(k) = (r(k) - al(k) * x(k-1)) * i_pivot
1368 i_pivot = 1.0 / (ac(n) + d1 * al(n))
1369 x(n) = (r(n) - al(n) * x(n-1)) * i_pivot
1372 x(k) = x(k) - c1(k) * x(k+1)
1375 end subroutine solve_diag_dominant_tridiag
1383 subroutine linear_solver( N, A, R, X )
1384 integer,
intent(in) :: N
1385 real,
dimension(N,N),
intent(inout) :: A
1386 real,
dimension(N),
intent(inout) :: R
1387 real,
dimension(N),
intent(inout) :: X
1399 do k=i,n ;
if ( abs(a(i,k)) > 0.0 )
exit ;
enddo 1402 call mom_error( fatal,
'The linear system sent to linear_solver is singular.' )
1408 do j=i,n ; swap = a(j,i) ; a(j,i) = a(j,k) ; a(j,k) = swap ;
enddo 1409 swap = r(i) ; r(i) = r(k) ; r(k) = swap
1413 i_pivot = 1.0 / a(i,i)
1415 do j=i+1,n ; a(j,i) = a(j,i) * i_pivot ;
enddo 1416 r(i) = r(i) * i_pivot
1422 do j=i+1,n ; a(j,k) = a(j,k) - factor * a(j,i) ;
enddo 1423 r(k) = r(k) - factor * r(i)
1429 if (a(n,n) == 0.0)
then 1431 call mom_error( fatal,
'The final pivot in linear_solver is zero.' )
1433 x(n) = r(n) / a(n,n)
1436 do j=i+1,n ; x(i) = x(i) - a(j,i) * x(j) ;
enddo 1439 end subroutine linear_solver
1444 subroutine test_line(msg, N, A, C, R, mag, tol)
1445 real,
intent(in) :: mag
1446 integer,
intent(in) :: N
1447 real,
dimension(4),
intent(in) :: A
1448 real,
dimension(4),
intent(in) :: C
1449 real,
intent(in) :: R
1450 character(len=*),
intent(in) :: msg
1451 real,
optional,
intent(in) :: tol
1453 real :: sum, sum_mag
1455 character(len=128) :: mesg2
1458 tolerance = 1.0e-12 ;
if (
present(tol)) tolerance = tol
1460 sum = 0.0 ; sum_mag = max(0.0,mag)
1462 sum = sum + a(i) * c(i)
1463 sum_mag = sum_mag + abs(a(i) * c(i))
1466 if (abs(sum - r) > tolerance * (sum_mag + abs(r)))
then 1467 write(mesg2,
'(", Fractional error = ", es12.4,", sum = ", es12.4)') (sum - r) / (sum_mag + abs(r)), sum
1468 call mom_error(fatal,
"Failed line test: "//trim(msg)//trim(mesg2))
1471 end subroutine test_line
Solvers of linear systems.
Routines for error handling and I/O management.
Edge value estimation for high-order resconstruction.