forked from MFlowCode/MFC
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathm_finite_differences.fpp
More file actions
141 lines (112 loc) · 5.89 KB
/
m_finite_differences.fpp
File metadata and controls
141 lines (112 loc) · 5.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
!>
!! @file
!! @brief Contains module m_finite_differences
#:include 'macros.fpp'
!> @brief Finite difference operators for computing divergence of velocity fields
module m_finite_differences
use m_global_parameters
implicit none
contains
subroutine s_compute_fd_divergence(div, fields, ix_s, iy_s, iz_s)
type(scalar_field), intent(INOUT) :: div
type(scalar_field), intent(IN) :: fields(1:3)
type(int_bounds_info), intent(IN) :: ix_s, iy_s, iz_s
integer :: x, y, z !< Generic loop iterators
real(wp) :: divergence
$:GPU_PARALLEL_LOOP(collapse=3, private='[x,y,z,divergence]')
do x = ix_s%beg, ix_s%end
do y = iy_s%beg, iy_s%end
do z = iz_s%beg, iz_s%end
if (x == ix_s%beg) then
divergence = (-3._wp*fields(1)%sf(x, y, z) + 4._wp*fields(1)%sf(x + 1, y, z) - fields(1)%sf(x + 2, y, z))/(x_cc(x + 2) - x_cc(x))
else if (x == ix_s%end) then
divergence = (+3._wp*fields(1)%sf(x, y, z) - 4._wp*fields(1)%sf(x - 1, y, z) + fields(1)%sf(x - 2, y, z))/(x_cc(x) - x_cc(x - 2))
else
divergence = (fields(1)%sf(x + 1, y, z) - fields(1)%sf(x - 1, y, z))/(x_cc(x + 1) - x_cc(x - 1))
end if
if (n > 0) then
if (y == iy_s%beg) then
divergence = divergence + (-3._wp*fields(2)%sf(x, y, z) + 4._wp*fields(2)%sf(x, y + 1, z) - fields(2)%sf(x, y + 2, z))/(y_cc(y + 2) - y_cc(y))
else if (y == iy_s%end) then
divergence = divergence + (+3._wp*fields(2)%sf(x, y, z) - 4._wp*fields(2)%sf(x, y - 1, z) + fields(2)%sf(x, y - 2, z))/(y_cc(y) - y_cc(y - 2))
else
divergence = divergence + (fields(2)%sf(x, y + 1, z) - fields(2)%sf(x, y - 1, z))/(y_cc(y + 1) - y_cc(y - 1))
end if
end if
if (p > 0) then
if (z == iz_s%beg) then
divergence = divergence + (-3._wp*fields(3)%sf(x, y, z) + 4._wp*fields(3)%sf(x, y, z + 1) - fields(3)%sf(x, y, z + 2))/(z_cc(z + 2) - z_cc(z))
else if (z == iz_s%end) then
divergence = divergence + (+3._wp*fields(3)%sf(x, y, z) - 4._wp*fields(3)%sf(x, y, z - 1) + fields(3)%sf(x, y, z - 2))/(z_cc(z) - z_cc(z - 2))
else
divergence = divergence + (fields(3)%sf(x, y, z + 1) - fields(3)%sf(x, y, z - 1))/(z_cc(z + 1) - z_cc(z - 1))
end if
end if
div%sf(x, y, z) = div%sf(x, y, z) + divergence
end do
end do
end do
$:END_GPU_PARALLEL_LOOP()
end subroutine s_compute_fd_divergence
!> The purpose of this subroutine is to compute the finite-
!! difference coefficients for the centered schemes utilized
!! in computations of first order spatial derivatives in the
!! s-coordinate direction. The s-coordinate direction refers
!! to the x-, y- or z-coordinate direction, depending on the
!! subroutine's inputs. Note that coefficients of up to 4th
!! order accuracy are available.
!! @param q Number of cells in the s-coordinate direction
!! @param s_cc Locations of the cell-centers in the s-coordinate direction
!! @param fd_coeff_s Finite-diff. coefficients in the s-coordinate direction
!! @param local_buff_size Size of the local buffer
!! @param fd_number_in Finite-difference number
!! @param fd_order_in Finite-difference order of accuracy
!! @param offset_s Optional offset bounds in the s-coordinate direction
subroutine s_compute_finite_difference_coefficients(q, s_cc, fd_coeff_s, local_buff_size, &
fd_number_in, fd_order_in, offset_s)
integer :: lB, lE !< loop bounds
integer, intent(IN) :: q
integer, intent(IN) :: local_buff_size, fd_number_in, fd_order_in
type(int_bounds_info), optional, intent(IN) :: offset_s
real(wp), allocatable, dimension(:, :), intent(INOUT) :: fd_coeff_s
real(wp), &
dimension(-local_buff_size:q + local_buff_size), &
intent(IN) :: s_cc
integer :: i !< Generic loop iterator
if (present(offset_s)) then
lB = -offset_s%beg
lE = q + offset_s%end
else
lB = 0
lE = q
end if
#ifdef MFC_POST_PROCESS
if (allocated(fd_coeff_s)) deallocate (fd_coeff_s)
allocate (fd_coeff_s(-fd_number_in:fd_number_in, lb:lE))
#endif
! Computing the 1st order finite-difference coefficients
if (fd_order_in == 1) then
do i = lB, lE
fd_coeff_s(-1, i) = 0._wp
fd_coeff_s(0, i) = -1._wp/(s_cc(i + 1) - s_cc(i))
fd_coeff_s(1, i) = -fd_coeff_s(0, i)
end do
! Computing the 2nd order finite-difference coefficients
elseif (fd_order_in == 2) then
do i = lB, lE
fd_coeff_s(-1, i) = -1._wp/(s_cc(i + 1) - s_cc(i - 1))
fd_coeff_s(0, i) = 0._wp
fd_coeff_s(1, i) = -fd_coeff_s(-1, i)
end do
! Computing the 4th order finite-difference coefficients
else
do i = lB, lE
fd_coeff_s(-2, i) = 1._wp/(s_cc(i - 2) - 8._wp*s_cc(i - 1) - s_cc(i + 2) + 8._wp*s_cc(i + 1))
fd_coeff_s(-1, i) = -8._wp*fd_coeff_s(-2, i)
fd_coeff_s(0, i) = 0._wp
fd_coeff_s(1, i) = -fd_coeff_s(-1, i)
fd_coeff_s(2, i) = -fd_coeff_s(-2, i)
end do
end if
end subroutine s_compute_finite_difference_coefficients
end module m_finite_differences