8 implicit none ;
private 10 public pqm_reconstruction, pqm_boundary_extrapolation, pqm_boundary_extrapolation_v1
12 real,
parameter :: hneglect_dflt = 1.e-30
20 subroutine pqm_reconstruction( N, h, u, edge_values, edge_slopes, ppoly_coef, h_neglect, answers_2018 )
21 integer,
intent(in) :: N
22 real,
dimension(:),
intent(in) :: h
23 real,
dimension(:),
intent(in) :: u
24 real,
dimension(:,:),
intent(inout) :: edge_values
25 real,
dimension(:,:),
intent(inout) :: edge_slopes
26 real,
dimension(:,:),
intent(inout) :: ppoly_coef
27 real,
optional,
intent(in) :: h_neglect
29 logical,
optional,
intent(in) :: answers_2018
39 call pqm_limiter( n, h, u, edge_values, edge_slopes, h_neglect, answers_2018 )
44 u0_l = edge_values(k,1)
45 u0_r = edge_values(k,2)
47 u1_l = edge_slopes(k,1)
48 u1_r = edge_slopes(k,2)
54 c = 30.0 * u(k) - 12.0*u0_r - 18.0*u0_l + 1.5*h_c*(u1_r - 3.0*u1_l)
55 d = -60.0 * u(k) + h_c *(6.0*u1_l - 4.0*u1_r) + 28.0*u0_r + 32.0*u0_l
56 e = 30.0 * u(k) + 2.5*h_c*(u1_r - u1_l) - 15.0*(u0_l + u0_r)
67 end subroutine pqm_reconstruction
75 subroutine pqm_limiter( N, h, u, edge_values, edge_slopes, h_neglect, answers_2018 )
76 integer,
intent(in) :: N
77 real,
dimension(:),
intent(in) :: h
78 real,
dimension(:),
intent(in) :: u
79 real,
dimension(:,:),
intent(inout) :: edge_values
80 real,
dimension(:,:),
intent(inout) :: edge_slopes
81 real,
optional,
intent(in) :: h_neglect
83 logical,
optional,
intent(in) :: answers_2018
87 integer :: inflexion_l
88 integer :: inflexion_r
93 real :: sigma_l, sigma_c, sigma_r
96 real :: alpha1, alpha2, alpha3
98 real :: gradient1, gradient2
102 hneglect = hneglect_dflt ;
if (
present(h_neglect)) hneglect = h_neglect
105 call bound_edge_values( n, h, u, edge_values, hneglect, answers_2018 )
108 call check_discontinuous_edge_values( n, u, edge_values )
119 u0_l = edge_values(k,1)
120 u0_r = edge_values(k,2)
121 u1_l = edge_slopes(k,1)
122 u1_r = edge_slopes(k,2)
134 sigma_l = 2.0 * ( u_c - u_l ) / ( h_c + hneglect )
135 sigma_c = 2.0 * ( u_r - u_l ) / ( h_l + 2.0*h_c + h_r + hneglect )
136 sigma_r = 2.0 * ( u_r - u_c ) / ( h_c + hneglect )
138 if ( (sigma_l * sigma_r) > 0.0 )
then 139 slope = sign( min(abs(sigma_l),abs(sigma_c),abs(sigma_r)), sigma_c )
146 if ( u1_l*slope <= 0.0 ) u1_l = slope
147 if ( u1_r*slope <= 0.0 ) u1_r = slope
150 if ( (u0_r - u_c) * (u_c - u0_l) <= 0.0)
then 163 if ( (inflexion_l == 0) .AND. (inflexion_r == 0) )
then 167 c = 30.0 * u(k) - 12.0*u0_r - 18.0*u0_l + 1.5*h_c*(u1_r - 3.0*u1_l)
168 d = -60.0 * u(k) + h_c *(6.0*u1_l - 4.0*u1_r) + 28.0*u0_r + 32.0*u0_l
169 e = 30.0 * u(k) + 2.5*h_c*(u1_r - u1_l) - 15.0*(u0_l + u0_r)
177 rho = alpha2 * alpha2 - 4.0 * alpha1 * alpha3
180 if (( alpha1 /= 0.0 ) .and. ( rho >= 0.0 ))
then 182 sqrt_rho = sqrt( rho )
184 x1 = 0.5 * ( - alpha2 - sqrt_rho ) / alpha1
185 x2 = 0.5 * ( - alpha2 + sqrt_rho ) / alpha1
188 if ( (x1 >= 0.0) .AND. (x1 <= 1.0) .AND. &
189 (x2 >= 0.0) .AND. (x2 <= 1.0) )
then 191 gradient1 = 4.0 * e * (x1**3) + 3.0 * d * (x1**2) + 2.0 * c * x1 + b
192 gradient2 = 4.0 * e * (x2**3) + 3.0 * d * (x2**2) + 2.0 * c * x2 + b
195 if ( (gradient1 * slope < 0.0) .OR. &
196 (gradient2 * slope < 0.0) )
then 199 if ( abs(sigma_l) < abs(sigma_r) )
then 208 elseif ( (x1 >= 0.0) .AND. (x1 <= 1.0) )
then 210 gradient1 = 4.0 * e * (x1**3) + 3.0 * d * (x1**2) + 2.0 * c * x1 + b
213 if ( gradient1 * slope < 0.0 )
then 216 if ( abs(sigma_l) < abs(sigma_r) )
then 224 elseif ( (x2 >= 0.0) .AND. (x2 <= 1.0) )
then 226 gradient2 = 4.0 * e * (x2**3) + 3.0 * d * (x2**2) + 2.0 * c * x2 + b
229 if ( gradient2 * slope < 0.0 )
then 232 if ( abs(sigma_l) < abs(sigma_r) )
then 245 if (( alpha1 == 0.0 ) .and. ( alpha2 /= 0.0 ))
then 247 x1 = - alpha3 / alpha2
248 if ( (x1 >= 0.0) .AND. (x1 <= 1.0) )
then 250 gradient1 = 4.0 * e * (x1**3) + 3.0 * d * (x1**2) + 2.0 * c * x1 + b
253 if ( gradient1 * slope < 0.0 )
then 256 if ( abs(sigma_l) < abs(sigma_r) )
then 270 if ( inflexion_l == 1 )
then 274 u1_l = ( 10.0 * u_c - 2.0 * u0_r - 8.0 * u0_l ) / (3.0*h_c + hneglect )
275 u1_r = ( -10.0 * u_c + 6.0 * u0_r + 4.0 * u0_l ) / ( h_c + hneglect )
281 if ( u1_l * slope < 0.0 )
then 284 u0_r = 5.0 * u_c - 4.0 * u0_l
285 u1_r = 20.0 * (u_c - u0_l) / ( h_c + hneglect )
287 elseif ( u1_r * slope < 0.0 )
then 290 u0_l = (5.0*u_c - 3.0*u0_r) / 2.0
291 u1_l = 10.0 * (-u_c + u0_r) / (3.0 * h_c + hneglect)
295 elseif ( inflexion_r == 1 )
then 299 u1_r = ( -10.0 * u_c + 8.0 * u0_r + 2.0 * u0_l ) / (3.0 * h_c + hneglect)
300 u1_l = ( 10.0 * u_c - 4.0 * u0_r - 6.0 * u0_l ) / (h_c + hneglect)
306 if ( u1_l * slope < 0.0 )
then 309 u0_r = ( 5.0 * u_c - 3.0 * u0_l ) / 2.0
310 u1_r = 10.0 * (u_c - u0_l) / (3.0 * h_c + hneglect)
312 elseif ( u1_r * slope < 0.0 )
then 315 u0_l = 5.0 * u_c - 4.0 * u0_r
316 u1_l = 20.0 * ( -u_c + u0_r ) / (h_c + hneglect)
323 edge_values(k,1) = u0_l
324 edge_values(k,2) = u0_r
325 edge_slopes(k,1) = u1_l
326 edge_slopes(k,2) = u1_r
331 edge_values(1,:) = u(1)
332 edge_slopes(1,:) = 0.0
334 edge_values(n,:) = u(n)
335 edge_slopes(n,:) = 0.0
337 end subroutine pqm_limiter
354 subroutine pqm_boundary_extrapolation( N, h, u, edge_values, ppoly_coef )
355 integer,
intent(in) :: N
356 real,
dimension(:),
intent(in) :: h
357 real,
dimension(:),
intent(in) :: u
358 real,
dimension(:,:),
intent(inout) :: edge_values
359 real,
dimension(:,:),
intent(inout) :: ppoly_coef
364 real :: a, b, c, d, e
385 slope = 2.0 * ( u1 - u0 )
386 if ( abs(u1_r) > abs(slope) )
then 392 u0_r = edge_values(i1,1)
397 u0_l = 3.0 * u0 + 0.5 * u1_r - 2.0 * u0_r
400 exp1 = (u0_r - u0_l) * (u0 - 0.5*(u0_l+u0_r))
401 exp2 = (u0_r - u0_l) * (u0_r - u0_l) / 6.0
403 if ( exp1 > exp2 )
then 404 u0_l = 3.0 * u0 - 2.0 * u0_r
407 if ( exp1 < -exp2 )
then 408 u0_r = 3.0 * u0 - 2.0 * u0_l
411 edge_values(i0,1) = u0_l
412 edge_values(i0,2) = u0_r
415 b = 6.0 * u0 - 4.0 * u0_l - 2.0 * u0_r
416 c = 3.0 * ( u0_r + u0_l - 2.0 * u0 )
422 ppoly_coef(i0,4) = 0.0
423 ppoly_coef(i0,5) = 0.0
439 u1_l = (b + 2*c + 3*d + 4*e)
440 u1_l = u1_l * (h1/h0)
443 slope = 2.0 * ( u1 - u0 )
444 if ( abs(u1_l) > abs(slope) )
then 450 u0_l = edge_values(i0,2)
455 u0_r = 3.0 * u1 - 0.5 * u1_l - 2.0 * u0_l
458 exp1 = (u0_r - u0_l) * (u1 - 0.5*(u0_l+u0_r))
459 exp2 = (u0_r - u0_l) * (u0_r - u0_l) / 6.0
461 if ( exp1 > exp2 )
then 462 u0_l = 3.0 * u1 - 2.0 * u0_r
465 if ( exp1 < -exp2 )
then 466 u0_r = 3.0 * u1 - 2.0 * u0_l
469 edge_values(i1,1) = u0_l
470 edge_values(i1,2) = u0_r
473 b = 6.0 * u1 - 4.0 * u0_l - 2.0 * u0_r
474 c = 3.0 * ( u0_r + u0_l - 2.0 * u1 )
480 ppoly_coef(i1,4) = 0.0
481 ppoly_coef(i1,5) = 0.0
483 end subroutine pqm_boundary_extrapolation
501 subroutine pqm_boundary_extrapolation_v1( N, h, u, edge_values, edge_slopes, ppoly_coef, h_neglect )
502 integer,
intent(in) :: N
503 real,
dimension(:),
intent(in) :: h
504 real,
dimension(:),
intent(in) :: u
505 real,
dimension(:,:),
intent(inout) :: edge_values
506 real,
dimension(:,:),
intent(inout) :: edge_slopes
507 real,
dimension(:,:),
intent(inout) :: ppoly_coef
508 real,
optional,
intent(in) :: h_neglect
512 integer :: inflexion_l
513 integer :: inflexion_r
516 real :: a, b, c, d, e
522 real :: alpha1, alpha2, alpha3
523 real :: rho, sqrt_rho
524 real :: gradient1, gradient2
528 hneglect = hneglect_dflt ;
if (
present(h_neglect)) hneglect = h_neglect
541 slope = 2.0 * ( u1 - u0 ) / ( ( h0 + h1 ) + hneglect )
550 u1_r = b / (h1 + hneglect)
555 beta = 2.0 * ( u0_r - um ) / ( (h0 + hneglect)*u1_r) - 1.0
559 br = u0_r + beta*u0_r - um
560 ar = um + beta*um - br
566 u_plm = um - 0.5 * slope
572 if ( abs(um-u0_l) < abs(um-u_plm) )
then 573 u1_l = 2.0 * ( br - ar*beta)
574 u1_l = u1_l / (h0 + hneglect)
577 u1_l = slope / (h0 + hneglect)
585 c = 30.0 * um - 12.0*u0_r - 18.0*u0_l + 1.5*h0*(u1_r - 3.0*u1_l)
586 d = -60.0 * um + h0 *(6.0*u1_l - 4.0*u1_r) + 28.0*u0_r + 32.0*u0_l
587 e = 30.0 * um + 2.5*h0*(u1_r - u1_l) - 15.0*(u0_l + u0_r)
593 rho = alpha2 * alpha2 - 4.0 * alpha1 * alpha3
597 if (( alpha1 /= 0.0 ) .and. ( rho >= 0.0 ))
then 599 sqrt_rho = sqrt( rho )
601 x1 = 0.5 * ( - alpha2 - sqrt_rho ) / alpha1
602 if ( (x1 > 0.0) .and. (x1 < 1.0) )
then 603 gradient1 = 4.0 * e * (x1**3) + 3.0 * d * (x1**2) + 2.0 * c * x1 + b
604 if ( gradient1 * slope < 0.0 )
then 609 x2 = 0.5 * ( - alpha2 + sqrt_rho ) / alpha1
610 if ( (x2 > 0.0) .and. (x2 < 1.0) )
then 611 gradient2 = 4.0 * e * (x2**3) + 3.0 * d * (x2**2) + 2.0 * c * x2 + b
612 if ( gradient2 * slope < 0.0 )
then 619 if (( alpha1 == 0.0 ) .and. ( alpha2 /= 0.0 ))
then 621 x1 = - alpha3 / alpha2
622 if ( (x1 >= 0.0) .and. (x1 <= 1.0) )
then 623 gradient1 = 3.0 * d * (x1**2) + 2.0 * c * x1 + b
624 if ( gradient1 * slope < 0.0 )
then 631 if ( inflexion_l == 1 )
then 635 u1_l = ( 10.0 * um - 2.0 * u0_r - 8.0 * u0_l ) / (3.0*h0 + hneglect)
636 u1_r = ( -10.0 * um + 6.0 * u0_r + 4.0 * u0_l ) / (h0 + hneglect)
642 if ( u1_l * slope < 0.0 )
then 645 u0_r = 5.0 * um - 4.0 * u0_l
646 u1_r = 20.0 * (um - u0_l) / ( h0 + hneglect )
648 elseif ( u1_r * slope < 0.0 )
then 651 u0_l = (5.0*um - 3.0*u0_r) / 2.0
652 u1_l = 10.0 * (-um + u0_r) / (3.0 * h0 + hneglect )
659 edge_values(i0,1) = u0_l
660 edge_values(i0,2) = u0_r
661 edge_slopes(i0,1) = u1_l
662 edge_slopes(i0,2) = u1_r
666 c = 30.0 * um - 12.0*u0_r - 18.0*u0_l + 1.5*h0*(u1_r - 3.0*u1_l)
667 d = -60.0 * um + h0 *(6.0*u1_l - 4.0*u1_r) + 28.0*u0_r + 32.0*u0_l
668 e = 30.0 * um + 2.5*h0*(u1_r - u1_l) - 15.0*(u0_l + u0_r)
688 slope = 2.0 * ( u1 - u0 ) / ( h0 + h1 )
698 u0_l = a + b + c + d + e
699 u1_l = (b + 2*c + 3*d + 4*e) / h0
703 if (um-u0_l /= 0.)
then 704 beta = 0.5*h1*u1_l / (um-u0_l) - 1.0
708 br = beta*um + um - u0_l
712 if (1+beta /= 0.)
then 713 u0_r = (ar + 2*br + beta*br ) / ((1+beta)*(1+beta))
715 u0_r = um + 0.5 * slope
719 u_plm = um + 0.5 * slope
725 if ( abs(um-u0_r) < abs(um-u_plm) )
then 726 u1_r = 2.0 * ( br - ar*beta ) / ( (1+beta)*(1+beta)*(1+beta) )
738 c = 30.0 * um - 12.0*u0_r - 18.0*u0_l + 1.5*h1*(u1_r - 3.0*u1_l)
739 d = -60.0 * um + h1*(6.0*u1_l - 4.0*u1_r) + 28.0*u0_r + 32.0*u0_l
740 e = 30.0 * um + 2.5*h1*(u1_r - u1_l) - 15.0*(u0_l + u0_r)
746 rho = alpha2 * alpha2 - 4.0 * alpha1 * alpha3
750 if (( alpha1 /= 0.0 ) .and. ( rho >= 0.0 ))
then 752 sqrt_rho = sqrt( rho )
754 x1 = 0.5 * ( - alpha2 - sqrt_rho ) / alpha1
755 if ( (x1 > 0.0) .and. (x1 < 1.0) )
then 756 gradient1 = 4.0 * e * (x1**3) + 3.0 * d * (x1**2) + 2.0 * c * x1 + b
757 if ( gradient1 * slope < 0.0 )
then 762 x2 = 0.5 * ( - alpha2 + sqrt_rho ) / alpha1
763 if ( (x2 > 0.0) .and. (x2 < 1.0) )
then 764 gradient2 = 4.0 * e * (x2**3) + 3.0 * d * (x2**2) + 2.0 * c * x2 + b
765 if ( gradient2 * slope < 0.0 )
then 772 if (( alpha1 == 0.0 ) .and. ( alpha2 /= 0.0 ))
then 774 x1 = - alpha3 / alpha2
775 if ( (x1 >= 0.0) .and. (x1 <= 1.0) )
then 776 gradient1 = 3.0 * d * (x1**2) + 2.0 * c * x1 + b
777 if ( gradient1 * slope < 0.0 )
then 784 if ( inflexion_r == 1 )
then 788 u1_r = ( -10.0 * um + 8.0 * u0_r + 2.0 * u0_l ) / (3.0 * h1)
789 u1_l = ( 10.0 * um - 4.0 * u0_r - 6.0 * u0_l ) / h1
795 if ( u1_l * slope < 0.0 )
then 798 u0_r = ( 5.0 * um - 3.0 * u0_l ) / 2.0
799 u1_r = 10.0 * (um - u0_l) / (3.0 * h1)
801 elseif ( u1_r * slope < 0.0 )
then 804 u0_l = 5.0 * um - 4.0 * u0_r
805 u1_l = 20.0 * ( -um + u0_r ) / h1
812 edge_values(i1,1) = u0_l
813 edge_values(i1,2) = u0_r
814 edge_slopes(i1,1) = u1_l
815 edge_slopes(i1,2) = u1_r
819 c = 30.0 * um - 12.0*u0_r - 18.0*u0_l + 1.5*h1*(u1_r - 3.0*u1_l)
820 d = -60.0 * um + h1 *(6.0*u1_l - 4.0*u1_r) + 28.0*u0_r + 32.0*u0_l
821 e = 30.0 * um + 2.5*h1*(u1_r - u1_l) - 15.0*(u0_l + u0_r)
829 end subroutine pqm_boundary_extrapolation_v1
Piecewise quartic reconstruction functions.
Edge value estimation for high-order resconstruction.