Report Typos and Errors    
Semi-Lagrangian Library
Modular library for kinetic and gyrokinetic simulations of plasmas in fusion energy devices.
sll_m_cubic_spline_halo_1d.F90
Go to the documentation of this file.
1 #ifdef USE_HALO_REAL32
2 #define HALO_DTYPE sll_real32
3 #else
4 #define HALO_DTYPE sll_real64
5 #endif
6 
7 ! NOTE: Check the initialization of pba_pow(:) below when changing NUM_TERMS.
8 ! Usual value (and maximum useful value in terms of double precision accuracy): 27
9 !!! #define NUM_TERMS 27
10 ! Temporarily reduced to 15 terms to enable the test case at 16**6 resolution.
11 #define NUM_TERMS 15
12 
13 ! Note: Uncomment one of the following macros to select how powers of p_b_a are computed.
14 ! fast, pre-computed array
15 #define PBA_POW(i) pba_pow(i)
16 ! slow, repeated computation, original implementation
17 !#define PBA_POW(i) (-p_b_a)**(i)
34 
35 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
36 #include "sll_assert.h"
37 #include "sll_memory.h"
38 #include "sll_working_precision.h"
39 
40  implicit none
41 
42  public :: &
48  private
49 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
50  ! Compile time constants for fast computations
51  sll_real64, parameter :: p_a = sqrt((2.0_f64 + sqrt(3.0_f64))/6.0_f64)
52  sll_real64, parameter :: p_r_a = 1.0_f64/p_a
53  sll_real64, parameter :: p_b = sqrt((2.0_f64 - sqrt(3.0_f64))/6.0_f64)
54  sll_real64, parameter :: p_b_a = p_b/p_a
55  sll_real64, parameter :: p_sqrt3 = sqrt(3.0_f64)
56  sll_real64, parameter :: p_inv_6 = 1._f64/6._f64
57 
58 ! $ cat pba_pow.py
59 ! for i in range(0,28): print ("(-p_b_a)**%d," % i),
60  sll_real64, dimension(0:27), parameter :: pba_pow = [ &
61  (-p_b_a)**0, (-p_b_a)**1, (-p_b_a)**2, (-p_b_a)**3, (-p_b_a)**4, (-p_b_a)**5, (-p_b_a)**6, &
62  (-p_b_a)**7, (-p_b_a)**8, (-p_b_a)**9, (-p_b_a)**10, (-p_b_a)**11, (-p_b_a)**12, (-p_b_a)**13, &
63  (-p_b_a)**14, (-p_b_a)**15, (-p_b_a)**16, (-p_b_a)**17, (-p_b_a)**18, (-p_b_a)**19, (-p_b_a)**20, &
64  (-p_b_a)**21, (-p_b_a)**22, (-p_b_a)**23, (-p_b_a)**24, (-p_b_a)**25, (-p_b_a)**26, (-p_b_a)**27 &
65  ]
66 
67 contains
68 
70 !DIR$ ATTRIBUTES FORCEINLINE :: sll_s_cubic_spline_halo_1d_prepare_exchange
71  subroutine sll_s_cubic_spline_halo_1d_prepare_exchange(fdata, si, num_points, d_0, c_np2)
72  sll_real64, intent(in) :: fdata(:)
73  sll_int32, intent(in) :: si
74  sll_int32, intent(in) :: num_points
75  halo_dtype, intent(out) :: d_0
76  halo_dtype, intent(out) :: c_np2
77 
78  sll_int32 :: i, ind_min
79 
80  ! Hard assert: In case less points are used buffer overruns do occur that may stay unnoticed!
81  sll_assert_always(num_points > num_terms)
82 
83  if (si > 0) then
84  d_0 = 0.0_f64
85  ind_min = si
86  else
87  d_0 = fdata(num_points + si)
88  ind_min = 1
89  end if
90  do i = ind_min, num_terms
91  d_0 = d_0 + pba_pow(i)*fdata(num_points + si - i)
92  end do
93  if (si < -1) then
94  c_np2 = 0.0_f64
95  ind_min = -si - 1
96  else
97  c_np2 = fdata(2 + si)
98  ind_min = 1
99  end if
100  do i = ind_min, num_terms
101  c_np2 = c_np2 + pba_pow(i)*fdata(2 + si + i)
102  end do
103  do i = 1, si + 1
104  c_np2 = c_np2 + pba_pow(i)*fdata(2 + si - i)
105  end do
107 
109 !DIR$ ATTRIBUTES FORCEINLINE :: sll_s_cubic_spline_halo_1d_finish_boundary_conditions
110  subroutine sll_s_cubic_spline_halo_1d_finish_boundary_conditions(fdata, si, num_points, d_0, c_np2)
111  sll_real64, intent(in) :: fdata(:)
112  sll_int32, intent(in) :: si
113  sll_int32, intent(in) :: num_points
114  halo_dtype, intent(out) :: d_0
115  halo_dtype, intent(inout) :: c_np2
116 
117  sll_int32 :: i, ind_min
118 
119  if (si > 0) then
120  d_0 = d_0 + fdata(si)
121  end if
122  do i = 1, si - 1
123  d_0 = d_0 + pba_pow(i)*fdata(si - i)
124  end do
125  d_0 = d_0*p_r_a
126  if (si < -1) then
127  c_np2 = c_np2 + fdata(num_points + 2 + si)
128  ind_min = 1
129  else
130  ind_min = si + 2
131  end if
132  do i = 1, -si - 2
133  c_np2 = c_np2 + pba_pow(i)*fdata(num_points + 2 + si + i)
134  end do
135  do i = ind_min, num_terms
136  c_np2 = c_np2 + pba_pow(i)*fdata(num_points + 2 + si - i)
137  end do
138  c_np2 = c_np2*p_sqrt3
140 
142 !DIR$ ATTRIBUTES FORCEINLINE :: sll_s_cubic_spline_halo_1d_compute_interpolant
143  subroutine sll_s_cubic_spline_halo_1d_compute_interpolant(f, num_points, d, coeffs)
144  sll_real64, intent(in) :: f(0:)
145  sll_int32, intent(in) :: num_points
146  sll_real64, intent(out) :: d(0:)
147  sll_real64, intent(out) :: coeffs(0:)
148 
149  sll_int32 :: i
150  sll_int32 :: np
151  logical, save :: first_call = .true.
152 
153  if ((first_call) .and. (num_terms < 27)) then
154  write (*, *) "WARNING: sll_s_cubic_spline_halo_1d uses NUM_TERMS=", num_terms
155  end if
156  first_call = .false.
157 
158  sll_assert(size(f) .ge. num_points - 1)
159  sll_assert(size(d) .ge. num_points)
160  sll_assert(size(coeffs) .ge. num_points)
161  ! Hard assert: In case less points are used buffer overruns do occur that may stay unnoticed!
162  sll_assert_always(num_points > num_terms)
163 
164  np = num_points
165  d(0) = f(0)
166 
167  do i = 1, np + 1
168  d(i) = p_r_a*(f(i) - p_b*d(i - 1))
169  end do
170  coeffs(np + 2) = f(np + 2)!d1*r_a
171  ! remaining coefficients:
172  do i = np + 1, 0, -1
173  coeffs(i) = p_r_a*(d(i) - p_b*coeffs(i + 1))
174  end do
176 
178 !DIR$ ATTRIBUTES FORCEINLINE :: sll_s_cubic_spline_halo_1d_eval_disp
179  subroutine sll_s_cubic_spline_halo_1d_eval_disp(coeffs, alpha, num_points, fout)
180  sll_real64, intent(in) :: coeffs(0:)
181  sll_real64, intent(in) :: alpha
182  sll_int32, intent(in) :: num_points
183  sll_real64, intent(out) :: fout(:)
184 
185  sll_real64 :: calpha, cim1, ci, cip1, cip2, t1, t2, t3, t4
186  sll_int32 :: cell
187 
188  calpha = 1.0_f64 - alpha
189 
190  do cell = 1, num_points
191  cim1 = coeffs(cell - 1)
192  ci = coeffs(cell)
193  cip1 = coeffs(cell + 1)
194  cip2 = coeffs(cell + 2)
195  t1 = 3.0_f64*ci
196  t3 = 3.0_f64*cip1
197  t2 = calpha*(calpha*(calpha*(cim1 - t1) + t1) + t1) + ci
198  t4 = alpha*(alpha*(alpha*(cip2 - t3) + t3) + t3) + cip1
199  fout(cell) = p_inv_6*(t2 + t4)
200  end do
202 
203 !DIR$ ATTRIBUTES FORCEINLINE :: sll_s_cubic_spline_halo_1d_periodic
204  subroutine sll_s_cubic_spline_halo_1d_periodic(fin, alpha, num_cells, fout)
205  sll_real64, intent(inout) :: fin(0:)
206  sll_real64, intent(in) :: alpha
207  sll_int32, intent(in) :: num_cells
208  sll_real64, intent(out) :: fout(:)
209 
210  call sll_s_cubic_spline_halo_1d_compute_periodic(num_cells, fout, fin)
211  call sll_s_cubic_spline_halo_1d_eval_disp(fin, alpha, num_cells, fout)
213 
215 !DIR$ ATTRIBUTES FORCEINLINE :: sll_s_cubic_spline_halo_1d_compute_periodic
216  subroutine sll_s_cubic_spline_halo_1d_compute_periodic(num_points, d, f_coeffs)
217  sll_int32, intent(in) :: num_points
218  sll_real64, intent(out) :: d(0:)
219  sll_real64, intent(inout) :: f_coeffs(0:)
220 
221  sll_int32 :: i
222  sll_int32 :: np
223  sll_assert(size(d) .ge. num_points)
224  sll_assert(size(f_coeffs) .ge. num_points)
225  ! Hard assert: In case less points are used buffer overruns do occur that may stay unnoticed!
226  sll_assert_always(num_points > num_terms)
227 
228  np = num_points
229  d(0) = f_coeffs(0)
230  do i = 1, num_terms
231  d(0) = d(0) + pba_pow(i)*f_coeffs(num_points - i)
232  end do
233  d(0) = d(0)*p_r_a
234 
235  do i = 1, np - 1
236  d(i) = p_r_a*(f_coeffs(i) - p_b*d(i - 1))
237  end do
238 
239  f_coeffs(np) = d(np - 1)
240  do i = 1, num_terms
241  f_coeffs(np) = f_coeffs(np) + d(i - 1)*pba_pow(i)
242  end do
243  f_coeffs(np) = f_coeffs(np)*p_r_a
244 
245  ! remaining coefficients:
246  do i = np - 1, 1, -1
247  f_coeffs(i) = p_r_a*(d(i - 1) - p_b*f_coeffs(i + 1))
248  end do
249 
250  f_coeffs(0) = f_coeffs(np)
251  f_coeffs(np + 1:np + 2) = f_coeffs(1:2)
253 
Interpolator 1d using cubic splines on regular mesh with halo cells.
subroutine, public sll_s_cubic_spline_halo_1d_compute_interpolant(f, num_points, d, coeffs)
Compute the coefficients of the local interpolating spline (after d(0) and c(num_points+2) have been ...
subroutine, public sll_s_cubic_spline_halo_1d_finish_boundary_conditions(fdata, si, num_points, d_0, c_np2)
Complete d(0) and c(num_points+2) with local data after their values have been received from the neig...
subroutine sll_s_cubic_spline_halo_1d_compute_periodic(num_points, d, f_coeffs)
Compute the coefficients of the local interpolating spline (after d(0) and c(num_points+2) have been ...
real(kind=f64), dimension(0:27), parameter pba_pow
subroutine, public sll_s_cubic_spline_halo_1d_periodic(fin, alpha, num_cells, fout)
subroutine, public sll_s_cubic_spline_halo_1d_prepare_exchange(fdata, si, num_points, d_0, c_np2)
Compute the part of d(0) and c(num_points+2) that need to be send to neighboring processors.
subroutine, public sll_s_cubic_spline_halo_1d_eval_disp(coeffs, alpha, num_points, fout)
This function corresponds to the interpolate_array_disp function of the interpolators but the displac...
    Report Typos and Errors