Report Typos and Errors    
Semi-Lagrangian Library
Modular library for kinetic and gyrokinetic simulations of plasmas in fusion energy devices.
sll_m_fcisl.F90
Go to the documentation of this file.
1 module sll_m_fcisl
2 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 #include "sll_assert.h"
4 #include "sll_memory.h"
5 #include "sll_working_precision.h"
6 
7  use sll_m_advection_1d_base, only: &
9 
10  use sll_m_cartesian_meshes, only: &
13 
14  implicit none
15 
16  public :: &
29 
30  private
31 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
32 
33 ! a direction is chosen for interpolation
34 ! derivative computation and advection
35 
37  sll_int32 :: degree
38  sll_real64, dimension(:, :), pointer :: buf
39  type(sll_t_cartesian_mesh_1d), pointer :: mesh_x1
40  type(sll_t_cartesian_mesh_1d), pointer :: mesh_x2
41  class(sll_c_advector_1d), pointer :: adv
42  sll_real64, dimension(:), pointer :: w
43  end type sll_t_oblic_derivative
44 
45 contains
46 
47  subroutine sll_s_compute_oblic_shift(iota, Nc_x1, shift, iota_modif)
48  sll_real64, intent(in) :: iota
49  sll_int32, intent(in) :: nc_x1
50  sll_int32, intent(out) :: shift
51  sll_real64, intent(out) :: iota_modif
52 
53  shift = floor(iota*nc_x1 + 0.5)
54  iota_modif = real(shift, f64)/real(nc_x1, f64)
55 
56  end subroutine sll_s_compute_oblic_shift
57 
58  subroutine sll_s_compute_iota_from_shift(Nc_x1, shift, iota_modif)
59  sll_int32, intent(in) :: nc_x1
60  sll_int32, intent(in) :: shift
61  sll_real64, intent(out) :: iota_modif
62 
63  iota_modif = real(shift, f64)/real(nc_x1, f64)
64 
65  end subroutine sll_s_compute_iota_from_shift
66 
67  !warning: normalization to correct/choose
69  f_input, &
70  f_output, &
71  Nc_x1, &
72  Nc_x2, &
73  adv, &
74  x1_min, &
75  x1_max, &
76  iota)
77  sll_real64, dimension(:, :), intent(in) :: f_input
78  sll_real64, dimension(:, :), intent(out) :: f_output
79  sll_int32, intent(in) :: nc_x1
80  sll_int32, intent(in) :: nc_x2
81  class(sll_c_advector_1d), pointer :: adv
82  sll_real64, intent(in) :: x1_min
83  sll_real64, intent(in) :: x1_max
84  sll_real64, intent(in) :: iota
85  !local variables
86  sll_int32 :: i
87  sll_real64 :: a
88  sll_real64 :: delta_x1
89  a = iota*real(nc_x1, f64)/real(nc_x2, f64)
90  delta_x1 = (x1_max - x1_min)/real(nc_x1, f64)
91 
92  do i = 1, nc_x2 + 1
93  call adv%advect_1d_constant( &
94  a, &
95  real(i - 1, f64)*delta_x1, &
96  f_input(1:nc_x1 + 1, i), &
97  f_output(1:nc_x1 + 1, i))
98  end do
99  end subroutine sll_s_compute_at_aligned
100 
102  Nc_x1, &
103  shift, &
104  spaghetti_size)
105  sll_int32, intent(in) :: nc_x1
106  sll_int32, intent(in) :: shift
107  sll_int32, intent(out) :: spaghetti_size
108  !local variables
109  sll_int32 :: i
110  sll_int32 :: i_loc
111 
112  spaghetti_size = 1
113  do i = 1, nc_x1
114  i_loc = modulo(i*shift, nc_x1)
115  if (i_loc .ne. 0) then
116  spaghetti_size = spaghetti_size + 1
117  else
118  exit
119  end if
120  end do
122 
123 
129  Nc_x1, &
130  Nc_x2, &
131  iota_guess, &
132  spaghetti_size_guess, &
133  shift, &
134  spaghetti_size)
135  sll_int32, intent(in) :: nc_x1
136  sll_int32, intent(in) :: nc_x2
137  !sll_int32, intent(in) :: shift_guess
138  sll_real64, intent(in) :: iota_guess
139  sll_int32, intent(in) :: spaghetti_size_guess
140  sll_int32, intent(out) :: shift
141  sll_int32, intent(out) :: spaghetti_size
142  !local variables
143  sll_int32 :: shift_guess
144  sll_int32 :: shift_plus
145  sll_int32 :: shift_minus
146  sll_int32 :: i
147  sll_int32 :: s
148  sll_int32 :: i_val
149  sll_int32 :: val
150  sll_int32 :: spaghetti_size_new
151 
152  sll_assert(nc_x1 > 0)
153  sll_assert(nc_x2 > 0)
154 
155  s = 0
156  val = 2*nc_x1
157  do i = -nc_x1, nc_x1
159  nc_x1, &
160  i, &
161  spaghetti_size)
162  if (abs(spaghetti_size_guess - spaghetti_size) < abs(val)) then
163  val = spaghetti_size_guess - spaghetti_size
164  i_val = i
165  if (val == 0) then
166  exit
167  end if
168  end if
169  end do
170 
172  nc_x1, &
173  i_val, &
174  spaghetti_size)
175 
176  shift_guess = floor(iota_guess*nc_x1)
177 
178  shift_plus = shift_guess
179  shift_minus = shift_guess
180 
181  do i = 0, nc_x1
183  nc_x1, &
184  shift_guess + i, &
185  spaghetti_size_new)
186  if (spaghetti_size_new .eq. spaghetti_size) then
187  shift_plus = shift_guess + i
188  exit
189  end if
190  end do
191  do i = 0, nc_x1
193  nc_x1, &
194  shift_guess - i, &
195  spaghetti_size_new)
196  if (spaghetti_size_new .eq. spaghetti_size) then
197  shift_minus = shift_guess - i
198  exit
199  end if
200  end do
201 
202  if (abs(shift_minus*nc_x1 - iota_guess) < abs(shift_plus*nc_x1 - iota_guess)) then
203  shift = shift_minus
204  else
205  shift = shift_plus
206  end if
207 
209  nc_x1, &
210  shift, &
211  spaghetti_size)
212 
213 ! call sll_s_compute_spaghetti_size_from_shift( &
214 ! Nc_x1, &
215 ! shift_guess, &
216 ! spaghetti_size)
217 
219 
221  Nc_x1, &
222  Nc_x2, &
223  shift, &
224  spaghetti_index, &
225  spaghetti_size)
226  sll_int32, intent(in) :: nc_x1
227  sll_int32, intent(in) :: nc_x2
228  sll_int32, intent(in) :: shift
229  sll_int32, dimension(:), intent(out) :: spaghetti_index
230  sll_int32, intent(out) :: spaghetti_size
231  !local variables
232  sll_int32 :: i
233  sll_int32 :: i_loc
234  sll_int32 :: ii
235  sll_int32 :: j
236  sll_int32 :: q
237  sll_int32, dimension(:), allocatable :: check
238  sll_int32 :: ierr
239 
240  sll_assert(nc_x1 > 0)
241  sll_assert(nc_x2 > 0)
242  sll_allocate(check(nc_x1 + 1), ierr)
243  !0, shift,2*shift, Nc_x1*shift
244  !while(modulo(k*shift,Nc_x1) .ne. 0)
245 
246  spaghetti_index = 0
247  spaghetti_index(1) = 1
248  spaghetti_size = 1
249  do i = 1, nc_x1
250  i_loc = modulo(i*shift, nc_x1)
251  if (i_loc .ne. 0) then
252  spaghetti_size = spaghetti_size + 1
253  spaghetti_index(i + 1) = i_loc + 1
254  else
255  exit
256  end if
257  end do
258  !print *,'#spaghetti_size=',shift,spaghetti_size
259  !print *,'#i,i_loc=',i,i_loc
260  q = nc_x1/spaghetti_size
261  do j = 1, q - 1
262  do ii = 1, spaghetti_size
263  spaghetti_index(ii + j*spaghetti_size) = modulo(spaghetti_index(ii) + j - 1, nc_x1) + 1
264  end do
265  end do
266  spaghetti_index(nc_x1 + 1) = spaghetti_index(1)
267  check = 0
268  do i = 1, nc_x1
269  if (spaghetti_index(i) < 1) then
270  print *, '#problem with spaghetti_index'
271  stop
272  end if
273  if (spaghetti_index(i) > nc_x1 + 1) then
274  print *, '#problem with spaghetti_index'
275  stop
276  end if
277  check(spaghetti_index(i)) = check(spaghetti_index(i)) + 1
278  !print *,i,spaghetti_index(i)
279  end do
280  if (maxval(check(1:nc_x1)) .ne. 1) then
281  print *, '#problem checking spaghetti_index'
282  print *, '#maxval=', maxval(check(1:nc_x1))
283  stop
284  end if
285  if (minval(check(1:nc_x1)) .ne. 1) then
286  print *, '#problem checking spaghetti_index'
287  print *, '#minval=', minval(check(1:nc_x1))
288  stop
289  end if
290 
291  end subroutine sll_s_compute_spaghetti
292 
293  subroutine sll_s_load_spaghetti( &
294  input, &
295  output, &
296  spaghetti_index, &
297  ! spaghetti_size, &
298  Npts_x1, &
299  Npts_x2)
300  sll_real64, dimension(:, :), intent(in) :: input
301  sll_real64, dimension(:), intent(out) :: output
302  sll_int32, dimension(:), intent(in) :: spaghetti_index
303 ! sll_int32, intent(in) :: spaghetti_size
304  sll_int32, intent(in) :: npts_x1
305  sll_int32, intent(in) :: npts_x2
306  !local variables
307  sll_int32 :: i
308  sll_int32 :: j
309  sll_int32 :: s
310  s = 0
311  do i = 1, npts_x1
312  do j = 1, npts_x2
313  s = s + 1
314  output(s) = input(spaghetti_index(i), j)
315  end do
316  end do
317  end subroutine sll_s_load_spaghetti
318 
320  input, &
321  output, &
322  spaghetti_index, &
323  ! spaghetti_size, &
324  Npts_x1, &
325  Npts_x2)
326  sll_real64, dimension(:), intent(in) :: input
327  sll_real64, dimension(:, :), intent(out) :: output
328  sll_int32, dimension(:), intent(in) :: spaghetti_index
329 ! sll_int32, intent(in) :: spaghetti_size
330  sll_int32, intent(in) :: npts_x1
331  sll_int32, intent(in) :: npts_x2
332  !local variables
333  sll_int32 :: i
334  sll_int32 :: j
335  sll_int32 :: s
336  s = 0
337  do i = 1, npts_x1
338  do j = 1, npts_x2
339  s = s + 1
340  output(spaghetti_index(i), j) = input(s)
341  end do
342  end do
343  end subroutine sll_s_unload_spaghetti
344 
346  degree, &
347  x1_min, &
348  x1_max, &
349  x2_min, &
350  x2_max, &
351  Nc_x1, &
352  Nc_x2, &
353  adv &
354  ) result(res)
355  type(sll_t_oblic_derivative), pointer :: res
356  sll_int32, intent(in) :: degree
357  sll_real64, intent(in) :: x1_min
358  sll_real64, intent(in) :: x1_max
359  sll_real64, intent(in) :: x2_min
360  sll_real64, intent(in) :: x2_max
361  sll_int32, intent(in) :: nc_x1
362  sll_int32, intent(in) :: nc_x2
363  class(sll_c_advector_1d), pointer :: adv
364  !local variables
365  sll_int32 :: ierr
366  sll_allocate(res, ierr)
368  res, &
369  degree, &
370  x1_min, &
371  x1_max, &
372  x2_min, &
373  x2_max, &
374  nc_x1, &
375  nc_x2, &
376  adv)
377 
378  end function sll_f_new_oblic_derivative
379 
381  deriv, &
382  degree, &
383  x1_min, &
384  x1_max, &
385  x2_min, &
386  x2_max, &
387  Nc_x1, &
388  Nc_x2, &
389  adv)
390  type(sll_t_oblic_derivative) :: deriv
391  sll_int32, intent(in) :: degree
392  sll_real64, intent(in) :: x1_min
393  sll_real64, intent(in) :: x1_max
394  sll_real64, intent(in) :: x2_min
395  sll_real64, intent(in) :: x2_max
396  sll_int32, intent(in) :: nc_x1
397  sll_int32, intent(in) :: nc_x2
398  class(sll_c_advector_1d), pointer :: adv
399  sll_int32 :: ierr
400 
401  deriv%degree = degree
402  deriv%mesh_x1 => sll_f_new_cartesian_mesh_1d(nc_x1, eta_min=x1_min, eta_max=x1_max)
403  deriv%mesh_x2 => sll_f_new_cartesian_mesh_1d(nc_x2, eta_min=x2_min, eta_max=x2_max)
404  deriv%adv => adv
405 
406  sll_allocate(deriv%buf(1:nc_x2 + 2*degree + 1, 1:nc_x1 + 1), ierr)
407  sll_allocate(deriv%w(-degree:nc_x2 + degree), ierr)
408 
409  call compute_finite_difference_init(deriv%w, 2*degree)
410 
411  end subroutine initialize_oblic_derivative
412 
413  subroutine sll_s_compute_w_hermite(w, r, s)
414  sll_int32, intent(in)::r, s
415  sll_real64, dimension(r:s), intent(out)::w
416  sll_int32 ::i, j
417  sll_real64::tmp
418 
419  !maple code for generation of w
420  !for k from r to -1 do
421  ! C[k]:=product((k-j),j=r..k-1)*product((k-j),j=k+1..s):
422  ! C[k]:=1/C[k]*product((-j),j=r..k-1)*product((-j),j=k+1..-1)*product((-j),j=1..s):
423  !od:
424  !for k from 1 to s do
425  ! C[k]:=product((k-j),j=r..k-1)*product((k-j),j=k+1..s):
426  ! C[k]:=1/C[k]*product((-j),j=r..-1)*product((-j),j=1..k-1)*product((-j),j=k+1..s):
427  !od:
428  !C[0]:=-add(C[k],k=r..-1)-add(C[k],k=1..s):
429 
430  do i = r, -1
431  tmp = 1._f64
432  do j = r, i - 1
433  tmp = tmp*real(i - j, f64)
434  end do
435  do j = i + 1, s
436  tmp = tmp*real(i - j, f64)
437  end do
438  tmp = 1._f64/tmp
439  do j = r, i - 1
440  tmp = tmp*real(-j, f64)
441  end do
442  do j = i + 1, -1
443  tmp = tmp*real(-j, f64)
444  end do
445  do j = 1, s
446  tmp = tmp*real(-j, f64)
447  end do
448  w(i) = tmp
449  end do
450 
451  do i = 1, s
452  tmp = 1._f64
453  do j = r, i - 1
454  tmp = tmp*real(i - j, f64)
455  end do
456  do j = i + 1, s
457  tmp = tmp*real(i - j, f64)
458  end do
459  tmp = 1._f64/tmp
460  do j = r, -1
461  tmp = tmp*real(-j, f64)
462  end do
463  do j = 1, i - 1
464  tmp = tmp*real(-j, f64)
465  end do
466  do j = i + 1, s
467  tmp = tmp*real(-j, f64)
468  end do
469  w(i) = tmp
470  end do
471  tmp = 0._f64
472  do i = r, -1
473  tmp = tmp + w(i)
474  end do
475  do i = 1, s
476  tmp = tmp + w(i)
477  end do
478  w(0) = -tmp
479 
480  !print *,'w',w
481  !do ii=r,s
482  ! print *,ii,w(r+s-ii)
483  !enddo
484  !
485 
486  end subroutine sll_s_compute_w_hermite
487 
489  input, &
490  output, &
491  Nc, &
492  w, &
493  r, &
494  s, &
495  length)
496  sll_real64, dimension(:), intent(in) :: input
497  sll_real64, dimension(:), intent(out) :: output
498  sll_int32, intent(in) :: nc
499  sll_int32, intent(in) :: r
500  sll_int32, intent(in) :: s
501  sll_real64, dimension(r:s), intent(in) :: w
502  sll_real64, intent(in) :: length
503  !local variables
504  sll_int32 :: i
505  sll_int32 :: ii
506  sll_real64 :: tmp
507  sll_int32 :: ind
508  sll_real64 :: dx
509  dx = length/real(nc, f64)
510  do i = 1, nc + 1
511  tmp = 0._f64
512  do ii = r, s
513  ind = modulo(i + ii - 1 + nc, nc) + 1
514  tmp = tmp + w(ii)*input(ind)
515  end do
516  output(i) = tmp/dx
517  end do
518 
519  end subroutine sll_s_compute_derivative_periodic
520 
522  integer, intent(in)::p
523  real(f64), dimension(-p/2:(p + 1)/2), intent(out)::w
524  integer::r, s, i, j
525  real(f64)::tmp
526 
527  r = -p/2
528  s = (p + 1)/2
529 
530 ! if(modulo(p,2)==0)then
531 ! r=-p/2
532 ! s=p/2
533 ! else
534 ! r=-(p-1)/2
535 ! s=(p+1)/2
536 ! endif
537 
538  !maple code for generation of w
539  !for k from r to -1 do
540  ! C[k]:=product((k-j),j=r..k-1)*product((k-j),j=k+1..s):
541  ! C[k]:=1/C[k]*product((-j),j=r..k-1)*product((-j),j=k+1..-1)*product((-j),j=1..s):
542  !od:
543  !for k from 1 to s do
544  ! C[k]:=product((k-j),j=r..k-1)*product((k-j),j=k+1..s):
545  ! C[k]:=1/C[k]*product((-j),j=r..-1)*product((-j),j=1..k-1)*product((-j),j=k+1..s):
546  !od:
547  !C[0]:=-add(C[k],k=r..-1)-add(C[k],k=1..s):
548 
549  do i = r, -1
550  tmp = 1._f64
551  do j = r, i - 1
552  tmp = tmp*real(i - j, f64)
553  end do
554  do j = i + 1, s
555  tmp = tmp*real(i - j, f64)
556  end do
557  tmp = 1._f64/tmp
558  do j = r, i - 1
559  tmp = tmp*real(-j, f64)
560  end do
561  do j = i + 1, -1
562  tmp = tmp*real(-j, f64)
563  end do
564  do j = 1, s
565  tmp = tmp*real(-j, f64)
566  end do
567  w(i) = tmp
568  end do
569 
570  do i = 1, s
571  tmp = 1._f64
572  do j = r, i - 1
573  tmp = tmp*real(i - j, f64)
574  end do
575  do j = i + 1, s
576  tmp = tmp*real(i - j, f64)
577  end do
578  tmp = 1._f64/tmp
579  do j = r, -1
580  tmp = tmp*real(-j, f64)
581  end do
582  do j = 1, i - 1
583  tmp = tmp*real(-j, f64)
584  end do
585  do j = i + 1, s
586  tmp = tmp*real(-j, f64)
587  end do
588  w(i) = tmp
589  end do
590  tmp = 0._f64
591  do i = r, -1
592  tmp = tmp + w(i)
593  end do
594  do i = 1, s
595  tmp = tmp + w(i)
596  end do
597  w(0) = -tmp
598 
599  end subroutine compute_finite_difference_init
600 
601 ! subroutine compute_field_from_phi_cartesian_1d(phi,mesh,A,interp)
602 ! sll_real64, dimension(:), intent(in) :: phi
603 ! sll_real64, dimension(:), intent(out) :: A
604 ! type(sll_t_cartesian_mesh_1d), pointer :: mesh
605 ! class(sll_c_interpolator_1d), pointer :: interp
606 ! sll_int32 :: Nc_x1
607 ! sll_real64 :: x1_min
608 ! sll_real64 :: delta_x1
609 ! sll_real64 :: x1
610 ! sll_int32 :: i1
611 !
612 ! Nc_x1 = mesh%num_cells
613 ! x1_min = mesh%eta_min
614 ! delta_x1 = mesh%delta_eta
615 !
616 ! call interp%compute_interpolants(phi)
617 !
618 ! do i1=1,Nc_x1+1
619 ! x1=x1_min+real(i1-1,f64)*delta_x1
620 ! A(i1)=interp%interpolate_from_interpolant_derivative_eta1(x1)
621 ! end do
622 ! end subroutine compute_field_from_phi_cartesian_1d
623 
624 end module sll_m_fcisl
Abstract class for advection.
Cartesian mesh basic types.
type(sll_t_cartesian_mesh_1d) function, pointer, public sll_f_new_cartesian_mesh_1d(num_cells, eta_min, eta_max)
allocates the memory space for a new 1D cartesian mesh on the heap, initializes it with the given arg...
subroutine, public sll_s_compute_derivative_periodic(input, output, Nc, w, r, s, length)
subroutine, public sll_s_unload_spaghetti(input, output, spaghetti_index, Npts_x1, Npts_x2)
subroutine, public sll_s_compute_spaghetti(Nc_x1, Nc_x2, shift, spaghetti_index, spaghetti_size)
subroutine compute_finite_difference_init(w, p)
subroutine, public sll_s_load_spaghetti(input, output, spaghetti_index, Npts_x1, Npts_x2)
subroutine, public sll_s_compute_spaghetti_size_from_shift(Nc_x1, shift, spaghetti_size)
subroutine, public sll_s_compute_spaghetti_and_shift_from_guess(Nc_x1, Nc_x2, iota_guess, spaghetti_size_guess, shift, spaghetti_size)
subroutine, public sll_s_compute_at_aligned(f_input, f_output, Nc_x1, Nc_x2, adv, x1_min, x1_max, iota)
Definition: sll_m_fcisl.F90:77
subroutine, public sll_s_compute_oblic_shift(iota, Nc_x1, shift, iota_modif)
Definition: sll_m_fcisl.F90:48
subroutine, public sll_s_compute_w_hermite(w, r, s)
subroutine, public sll_s_compute_iota_from_shift(Nc_x1, shift, iota_modif)
Definition: sll_m_fcisl.F90:59
subroutine initialize_oblic_derivative(deriv, degree, x1_min, x1_max, x2_min, x2_max, Nc_x1, Nc_x2, adv)
type(sll_t_oblic_derivative) function, pointer, public sll_f_new_oblic_derivative(degree, x1_min, x1_max, x2_min, x2_max, Nc_x1, Nc_x2, adv)
    Report Typos and Errors