Report Typos and Errors    
Semi-Lagrangian Library
Modular library for kinetic and gyrokinetic simulations of plasmas in fusion energy devices.
sll_m_advection_1d_CSL_periodic.F90
Go to the documentation of this file.
1 !**************************************************************
2 ! Copyright INRIA
3 ! Authors :
4 ! CALVI project team
5 !
6 ! This code SeLaLib (for Semi-Lagrangian-Library)
7 ! is a parallel library for simulating the plasma turbulence
8 ! in a tokamak.
9 !
10 ! This software is governed by the CeCILL-B license
11 ! under French law and abiding by the rules of distribution
12 ! of free software. You can use, modify and redistribute
13 ! the software under the terms of the CeCILL-B license as
14 ! circulated by CEA, CNRS and INRIA at the following URL
15 ! "http://www.cecill.info".
16 !**************************************************************
17 
18 ! in development; should be at least cubic splines
19 ! attached with computation of characteristics
20 
24 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
25 #include "sll_errors.h"
26 #include "sll_memory.h"
27 #include "sll_working_precision.h"
28 
29 ! use F77_fftpack, only: &
30 ! dfftb, &
31 ! dfftf
32 
33  use sll_m_advection_1d_base, only: &
35 
39 
42 
45 
46  use sll_m_interpolators_1d_base, only: &
48 
49  use sll_m_lagrange_interpolation, only: &
51 
52  implicit none
53 
54  public :: &
56 
57  private
58 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
59 
61 
62  class(sll_c_interpolator_1d), pointer :: interp
63  class(sll_c_characteristics_1d_base), pointer :: charac
64  sll_real64, dimension(:), pointer :: eta_coords
65  sll_real64, dimension(:), pointer :: charac_feet
66  sll_real64, dimension(:), pointer :: charac_feet_inside
67  !sll_real64, dimension(:), pointer :: csl_mat_init
68  !sll_real64, dimension(:), pointer :: csl_mat
69  !sll_real64, dimension(:), pointer :: fft_buf
70  sll_real64, dimension(:, :), pointer :: deriv
71  sll_int32 :: npts
72  sll_int32 :: csl_degree
73  contains
74  procedure, pass(adv) :: initialize => &
76  procedure, pass(adv) :: advect_1d => &
78  procedure, pass(adv) :: advect_1d_constant => &
80  procedure, pass(adv) :: delete => delete_csl_periodic_1d_adv
82 
83 contains
85  interp, &
86  charac, &
87  Npts, &
88  eta_min, &
89  eta_max, &
90  eta_coords, &
91  csl_degree) &
92  result(adv)
93  type(csl_periodic_1d_advector), pointer :: adv
94  class(sll_c_interpolator_1d), pointer :: interp
95  class(sll_c_characteristics_1d_base), pointer :: charac
96  sll_int32, intent(in) :: npts
97  sll_real64, intent(in), optional :: eta_min
98  sll_real64, intent(in), optional :: eta_max
99  sll_real64, dimension(:), pointer, optional :: eta_coords
100  sll_int32, intent(in), optional :: csl_degree
101  sll_int32 :: ierr
102 
103  sll_allocate(adv, ierr)
104 
106  adv, &
107  interp, &
108  charac, &
109  npts, &
110  eta_min, &
111  eta_max, &
112  eta_coords, &
113  csl_degree)
114 
116 
118  adv, &
119  interp, &
120  charac, &
121  Npts, &
122  eta_min, &
123  eta_max, &
124  eta_coords, &
125  csl_degree)
126  class(csl_periodic_1d_advector), intent(inout) :: adv
127  class(sll_c_interpolator_1d), pointer :: interp
128  class(sll_c_characteristics_1d_base), pointer :: charac
129  sll_int32, intent(in) :: npts
130  sll_real64, intent(in), optional :: eta_min
131  sll_real64, intent(in), optional :: eta_max
132  sll_real64, dimension(:), pointer, optional :: eta_coords
133  sll_int32, optional :: csl_degree
134  sll_int32 :: ierr
135  sll_int32 :: i
136  sll_real64 :: delta_eta
137  !sll_real64 :: hermite_inversibility
138 
139  !hermite_inversibility = 1._f64
140 
141  if (present(csl_degree)) then
142  adv%csl_degree = csl_degree
143  else
144  adv%csl_degree = 3
145  end if
146 
147  adv%Npts = npts
148  adv%interp => interp
149  adv%charac => charac
150  sll_allocate(adv%eta_coords(npts), ierr)
151 
152  sll_allocate(adv%charac_feet(npts), ierr)
153  sll_allocate(adv%charac_feet_inside(npts), ierr)
154  !SLL_ALLOCATE(adv%csl_mat(Npts-1),ierr)
155  !SLL_ALLOCATE(adv%csl_mat_init(Npts-1),ierr)
156  !SLL_ALLOCATE(adv%fft_buf(2*(Npts-1)+15),ierr)
157  sll_allocate(adv%deriv(2, npts - 1), ierr)
158 
159  !call dffti(Npts-1,adv%fft_buf)
160 
161  if (present(eta_min) .and. present(eta_max)) then
162  if (present(eta_coords)) then
163  print *, '#provide either eta_coords or eta_min and eta_max'
164  print *, '#and not both in subroutine initialize_BSL_1d_advector'
165  stop
166  else
167  delta_eta = (eta_max - eta_min)/real(npts - 1, f64)
168  do i = 1, npts
169  adv%eta_coords(i) = eta_min + real(i - 1, f64)*delta_eta
170  end do
171  end if
172  else if (present(eta_coords)) then
173  if (size(eta_coords) < npts) then
174  print *, '#bad size for eta_coords in initialize_BSL_1d_advector'
175  stop
176  else
177  adv%eta_coords(1:npts) = eta_coords(1:npts)
178  end if
179  else
180  print *, '#Warning, we assume eta_min = 0._f64 eta_max = 1._f64'
181  delta_eta = 1._f64/real(npts - 1, f64)
182  do i = 1, npts
183  adv%eta_coords(i) = real(i - 1, f64)*delta_eta
184  end do
185  end if
186 
187 ! call compute_csl_mat( &
188 ! interp, &
189 ! adv%eta_coords(1), &
190 ! adv%eta_coords(Npts), &
191 ! Npts, &
192 ! adv%csl_mat)
193 
194  !if(present(hermite_degree))then
195  ! call compute_csl_hermite_mat( &
196  ! hermite_degree, &
197  ! Npts-1,adv%csl_mat)
198  !print *,'#hermite_degree=',hermite_degree
199  !print *,'#csl_mat='
200  !do i=1,Npts-1
201  ! print *,i,adv%csl_mat(i)
202  !enddo
203  !stop
204  !do i=1,Npts-1
205  ! adv%csl_mat_init(i) = adv%csl_mat(i)
206  !enddo
207 
208  !call dfftf(Npts-1,adv%csl_mat,adv%fft_buf)
209  !hermite_inversibility = abs(adv%csl_mat(1))
210  !print *,0,adv%csl_mat(1)
211  !do i=1,(Npts-1)/2
212  !print *,i-1,adv%csl_mat(2*(i-1)),adv%csl_mat(2*(i-1)+1), &
213  !hermite_inversibility = min(hermite_inversibility, &
214  ! sqrt(adv%csl_mat(2*i)**2+adv%csl_mat(2*i+1)**2))
215  !enddo
216  !if(mod(Npts-1,2)==0)then
217  ! print *,(Npts-1)/2,adv%csl_mat(Npts-1)
218  !endif
219 
220  !print *,'#hermite_inversibility=',hermite_inversibility
221  !if(hermite_inversibility<1.-12)then
222  ! print *,'#csl_mat not invertible',hermite_inversibility
223  ! stop
224  !endif
225  !call compute_inverse_csl_hermite_mat(Npts-1,adv%csl_mat)
226 
227  !call check_solve_csl_mat( &
228  ! adv%csl_mat, &
229  ! adv%csl_mat_init, &
230  ! Npts-1, &
231  ! adv%fft_buf)
232 
233  !print *,'#inverse mat'
234  !do i=1,Npts-1
235  ! print *,i,adv%csl_mat(i)*sqrt(real(Npts-1,f64))
236  !enddo
237  !stop
238 
240 
242  adv, &
243  A, &
244  dt, &
245  input, &
246  output)
247  class(csl_periodic_1d_advector) :: adv
248  sll_real64, dimension(:), intent(in) :: a
249  sll_real64, intent(in) :: dt
250  sll_real64, dimension(:), intent(in) :: input
251  sll_real64, dimension(:), intent(out) :: output
252  sll_int32 :: i
253 
254  call adv%charac%compute_characteristics( &
255  a, &
256  dt, &
257  adv%eta_coords, &
258  adv%charac_feet)
259 
260  call check_charac_feet( &
261  adv%eta_coords, &
262  adv%charac_feet, &
263  adv%Npts)
264 
265  do i = 1, adv%Npts
266  adv%charac_feet_inside(i) = &
268  adv%charac_feet(i), &
269  adv%eta_coords(1), &
270  adv%eta_coords(adv%Npts))
271  end do
272  call adv%interp%compute_interpolants(input)
273 
274  !compute the derivatives at time tn
275  !for future use in Hermite form
277  adv%interp, &
278  adv%deriv, &
279  adv%Npts - 1, &
280  adv%eta_coords(1), &
281  adv%eta_coords(adv%Npts))
282 
284  adv%interp, &
285  input, &
286  adv%deriv, &
287  adv%charac_feet, &
288  adv%Npts, &
289  adv%eta_coords(1), &
290  adv%eta_coords(adv%Npts), &
291  output, &
292  adv%csl_degree)
293 
294 ! call compute_csl_integral( &
295 ! adv%Npts, &
296 ! adv%interp, &
297 ! adv%eta_coords, &
298 ! adv%charac_feet, &
299 ! output(1:adv%Npts-1))
300 ! if(maxval(input)>1.e-1)then
301 ! print *,'before'
302 ! do i=1,adv%Npts-1
303 ! print *,i,input(i),output(i),0.5_f64*(input(i)+input(i+1))
304 ! enddo
305 !! stop
306 ! endif
307 
308 ! call mult_circulant_mat( &
309 ! adv%Npts-1, &
310 ! adv%csl_mat, &
311 ! output(1:adv%Npts-1), &
312 ! adv%fft_buf)
313 !
314 ! output(adv%Npts) = output(1)
315 ! if(maxval(input)>1.e-1)then
316 ! print *,'after'
317 ! do i=1,adv%Npts-1
318 ! print *,i,input(i),output(i),0.5_f64*(output(i)+output(i+1))
319 ! !adv%csl_mat_init(i)
320 ! enddo
321 ! stop
322 ! endif
323 ! call adv%interp%compute_interpolants( &
324 ! input, &
325 ! adv%eta1_coords, &
326 ! adv%Npts1, &
327 ! adv%eta2_coords, &
328 ! adv%Npts2 )
329 
330 ! output = adv%interp%interpolate_array( &
331 ! adv%Npts, &
332 ! input, &
333 ! adv%charac_feet_inside)
334 
335  end subroutine csl_periodic_advect_1d
336 
338  adv, &
339  A, &
340  dt, &
341  input, &
342  output)
343  class(csl_periodic_1d_advector) :: adv
344  sll_real64, intent(in) :: a
345  sll_real64, intent(in) :: dt
346  sll_real64, dimension(:), intent(in) :: input
347  sll_real64, dimension(:), intent(out) :: output
348  sll_real64, dimension(:), allocatable :: a1
349  sll_int32 :: ierr
350 
351  !this version is not optimized
352 
353  sll_allocate(a1(adv%Npts), ierr)
354 
355  a1 = a
356 
357  call adv%charac%compute_characteristics( &
358  a1, &
359  dt, &
360  adv%eta_coords, &
361  adv%charac_feet)
362 
363 ! call adv%interp%compute_interpolants( &
364 ! input, &
365 ! adv%eta1_coords, &
366 ! adv%Npts1, &
367 ! adv%eta2_coords, &
368 ! adv%Npts2 )
369 
370  call adv%interp%interpolate_array( &
371  adv%Npts, &
372  input, &
373  adv%charac_feet, &
374  output)
375 
376  sll_deallocate_array(a1, ierr)
377 
378  end subroutine csl_periodic_advect_1d_constant
379 
381  class(csl_periodic_1d_advector), intent(inout) :: adv
382  sll_int32 :: ierr
383  sll_deallocate(adv%eta_coords, ierr)
384  sll_deallocate(adv%charac_feet, ierr)
385  end subroutine delete_csl_periodic_1d_adv
386 
387  subroutine check_charac_feet( &
388  origin, &
389  feet, &
390  Npts, &
391  epsilon)
392  sll_real64, dimension(:), intent(in) :: origin
393  sll_real64, dimension(:), intent(inout) :: feet
394  sll_int32, intent(in) :: npts
395  sll_real64, intent(in), optional :: epsilon
396  sll_real64 :: length
397  sll_real64 :: gap_min
398  sll_real64 :: gap_max
399  !sll_int32 :: i
400  sll_real64 :: eps
401 
402  if (size(origin) < npts) then
403  sll_error("check_charac_feet", "bad size for origin")
404  end if
405  if (size(feet) < npts) then
406  sll_error("check_charac_feet", "bad size for feet")
407  end if
408  length = origin(npts) - origin(1)
409  feet(npts) = feet(1) + length !added because errors
410  if (abs(length - (feet(npts) - feet(1))) > 1.e-12_f64) then
411  print *, 'origin', origin
412  print *, 'feet', feet
413  print *, feet(npts) - feet(1), origin(npts) - origin(1)
414  sll_error("check_charac_feet", "bad length")
415  end if
416 
417  if (present(epsilon)) then
418  eps = epsilon
419  else
420  eps = 1.e-12_f64
421  end if
422 
423  gap_min = compute_gap_min(origin, npts)
424  gap_max = compute_gap_max(origin, npts)
425 
426  !print *,'#gap1',gap_min,gap_max
427  if (gap_min <= eps) then
428  sll_error("check_charac_feet", "bad gap_min")
429  end if
430 
431  gap_min = compute_gap_min(feet, npts)
432  gap_max = compute_gap_max(feet, npts)
433  !print *,'#gap2',gap_min,gap_max
434  if (gap_min <= eps) then
435  sll_error("check_charac_feet", "pb for charac_feet")
436  end if
437 
438  end subroutine check_charac_feet
439 
440  function compute_gap_min(input, Npts) result(res)
441  sll_real64, dimension(:), intent(in) :: input
442  sll_int32, intent(in) :: npts
443  sll_real64 :: res
444  sll_int32 :: i
445  sll_real64 :: val
446 
447  if (size(input) <= 1) then
448  sll_error("compute_gap_min", "bad size for input")
449  end if
450  res = input(2) - input(1)
451  do i = 1, npts - 1
452  val = input(i + 1) - input(i)
453  if (val < res) then
454  res = val
455  end if
456  end do
457 
458  end function compute_gap_min
459 
460  function compute_gap_max(input, Npts) result(res)
461  sll_real64, dimension(:), intent(in) :: input
462  sll_int32, intent(in) :: npts
463  sll_real64 :: res
464  sll_int32 :: i
465  sll_real64 :: val
466 
467  if (size(input) <= 1) then
468  sll_error("compute_gap_max", "bad size for input")
469  end if
470  res = input(2) - input(1)
471  do i = 1, npts - 1
472  val = input(i + 1) - input(i)
473  if (val > res) then
474  res = val
475  end if
476  end do
477 
478  end function compute_gap_max
479 
480  subroutine compute_csl_hermite_mat(d, N, output)
481  sll_int32, intent(in) :: d
482  sll_int32, intent(in) :: n
483  sll_real64, dimension(:), intent(out) :: output
484  sll_real64 :: w_left(-d/2:(d + 1)/2)
485  sll_real64 :: w_right((-d + 1)/2:d/2 + 1)
486  !sll_real64 :: tmp
487  sll_int32 :: r_left
488  sll_int32 :: r_right
489  sll_int32 :: s_left
490  sll_int32 :: s_right
491  sll_int32 :: i
492  sll_int32 :: ind
493 
494  if (n < 1) then
495  sll_error("csl_hermite_mat", "bad size of N")
496  end if
497 
498  if (d < 0) then
499  sll_error("csl_hermite_mat", "bad size of d")
500  end if
501 
502  if (size(output) < n) then
503  sll_error("csl_hermite_mat", "bad size of output")
504  end if
505  output(1:n) = 0._f64
506  output(1) = 0.5_f64
507  !output(2) = 0.5_f64
508  output(n) = 0.5_f64 !because we have to take a_{-i}
509  !instead of a_i, if we want to perform further fft of a
510 
511  r_left = -d/2
512  s_left = (d + 1)/2
513  r_right = (-d + 1)/2
514  s_right = d/2 + 1
515 
516  call sll_s_compute_w_hermite_1d(w_left, r_left, s_left)
517  if ((2*(d/2) - d) == 0) then
518  w_right(r_right:s_right) = w_left(r_left:s_left)
519  else
520  w_right(r_right:s_right) = -w_left(s_left:r_left:-1)
521  end if
522 
523  do i = r_left, s_left
524  ind = 1 + modulo(i, n)!1+modulo(-i+N,N)
525  ind = 1 + modulo(n - ind, n)
526  output(ind) = output(ind) + w_left(i)/12._f64
527  end do
528  do i = r_right, s_right
529  ind = 1 + modulo(i, n)!1+modulo(-i+N,N)
530  ind = 1 + modulo(n - ind, n)
531  output(ind) = output(ind) - w_right(i)/12._f64
532  end do
533 
534  end subroutine compute_csl_hermite_mat
535 
537  sll_int32, intent(in) :: n
538  sll_real64, dimension(:), intent(inout) :: mat
539  sll_int32 :: i
540  sll_real64 :: rea
541  sll_real64 :: ima
542  sll_real64 :: val
543 
544  if (n < 1) then
545  print *, '#N=', n
546  sll_error("csl_hermite_mat", "bad size of N")
547  end if
548  if (size(mat) < n) then
549  print *, '#N=', n
550  print *, '#size(mat)=', size(mat)
551  sll_error("csl_hermite_mat", "bad size of mat")
552  end if
553 
554  mat(1) = 1._f64/(mat(1)*real(n, f64))
555  do i = 1, (n - 1)/2
556  rea = mat(2*i)
557  ima = mat(2*i + 1)
558  val = 1._f64/((rea**2 + ima**2)*real(n, f64))
559  mat(2*i) = rea*val
560  mat(2*i + 1) = -ima*val
561  end do
562  if (mod(n, 2) == 0) then
563  !the matrix is not invertible
564  if (abs(mat(n)) < 1.e-12) then
565  mat(n) = 0._f64
566  !the matrix is invertible
567  else
568  if (abs(mat(n)) < 1.e-6) then
569  print *, '#mat(N)=', mat(n)
570  sll_warning("compute_inverse_csl_hermite_mat", "mat(N) small")
571  end if
572  mat(n) = 1._f64/(mat(n)*real(n, f64))
573  end if
574  end if
575 
576  end subroutine compute_inverse_csl_hermite_mat
577 
578  subroutine mult_circulant_mat(N, mat, f, fft_buf)
579  sll_int32, intent(in) :: n
580  sll_real64, dimension(:), intent(in) :: mat
581  sll_real64, dimension(:), intent(inout) :: f
582  sll_real64, dimension(:), intent(in) :: fft_buf
583  sll_int32 :: i
584  sll_real64 :: rea
585  sll_real64 :: ima
586  sll_real64 :: reb
587  sll_real64 :: imb
588 
589  call dfftf(n, f, fft_buf)
590  f(1) = f(1)*mat(1)
591  do i = 1, (n - 1)/2
592  rea = f(2*i)
593  ima = f(2*i + 1)
594  reb = mat(2*i)
595  imb = mat(2*i + 1)
596  f(2*i) = rea*reb - ima*imb
597  f(2*i + 1) = rea*imb + reb*ima
598  end do
599  if (mod(n, 2) == 0) f(n) = f(n)*mat(n)
600  call dfftb(n, f, fft_buf)
601 
602  end subroutine mult_circulant_mat
603 
604  subroutine compute_csl_integral( &
605  Npts, &
606  interp, &
607  origin, &
608  feet, &
609  output)
610  sll_int32, intent(in) :: npts
611  class(sll_c_interpolator_1d), pointer :: interp
612  sll_real64, dimension(:), intent(in) :: origin
613  sll_real64, dimension(:), intent(in) :: feet
614  sll_real64, dimension(:), intent(out) :: output
615  sll_real64 :: eta_min
616  sll_real64 :: eta_max
617  sll_real64 :: delta
618  sll_real64 :: val
619  sll_real64 :: a
620  sll_real64 :: b
621  sll_int32 :: i
622  sll_int32 :: ii
623  sll_int32 :: i_min
624  sll_int32 :: i_max
625 
626  if (size(output) < npts - 1) then
627  print *, 'Npts-1=', npts - 1
628  print *, 'size(output)=', size(output)
629  sll_error("compute_csl_integral", "bad size of output")
630  end if
631  if (size(origin) < npts) then
632  print *, 'Npts=', npts
633  print *, 'size(origin)=', size(origin)
634  sll_error("compute_csl_integral", "bad size of origin")
635  end if
636  if (size(feet) < npts) then
637  print *, 'Npts=', npts
638  print *, 'size(feet)=', size(feet)
639  sll_error("compute_csl_integral", "bad size of feet")
640  end if
641 
642  !we assume uniform mesh for origin
643  eta_min = origin(1)
644  eta_max = origin(npts)
645  delta = (eta_max - eta_min)/real(npts - 1, f64)
646 
647  do i = 1, npts - 1
648  i_min = floor((feet(i) - eta_min)/delta)
649  i_max = floor((feet(i + 1) - eta_min)/delta)
650  if (i_min == i_max) then
651  a = feet(i)
652  b = feet(i + 1)
653  val = compute_simpson_contribution_csl_periodic(interp, a, b, eta_min, eta_max)
654  else
655  if (i_min > i_max) then
656  print *, 'i_min,i_max=', i_min, i_max
657  sll_error("compute_csl_integral", "bad value of i_min/i_max")
658  end if
659  a = feet(i)
660  b = eta_min + real(i_min + 1, f64)*delta
661  val = compute_simpson_contribution_csl_periodic(interp, a, b, eta_min, eta_max)
662  do ii = i_min + 1, i_max - 1
663  a = eta_min + real(ii, f64)*delta
664  b = eta_min + real(ii + 1, f64)*delta
665  val = val + compute_simpson_contribution_csl_periodic(interp, a, b, eta_min, eta_max)
666  end do
667  a = eta_min + real(i_max, f64)*delta
668  b = feet(i + 1)
669  val = val + compute_simpson_contribution_csl_periodic(interp, a, b, eta_min, eta_max)
670  end if
671  output(i) = val/delta
672  end do
673 
674  !print *,minval(output),maxval(output)
675 
676  end subroutine compute_csl_integral
677 
679  interp, &
680  a, &
681  b, &
682  eta_min, &
683  eta_max) &
684  result(res)
685  class(sll_c_interpolator_1d), pointer :: interp
686  sll_real64, intent(in) :: a
687  sll_real64, intent(in) :: b
688  sll_real64, intent(in) :: eta_min
689  sll_real64, intent(in) :: eta_max
690  sll_real64 :: eta
691  sll_real64 :: res
692  sll_real64 :: nodes(3, 2)
693  sll_int32 :: j
694 
695  nodes(1, 1) = a
696  nodes(3, 1) = b
697  nodes(2, 1) = 0.5_f64*(a + b)
698  do j = 1, 3
700  nodes(j, 1), &
701  eta_min, &
702  eta_max)
703  nodes(j, 2) = interp%interpolate_from_interpolant_value(eta)
704  end do
705  res = nodes(1, 2) + 4._f64*nodes(2, 2) + nodes(3, 2)
706  res = res*(b - a)/6._f64
707 
709 
710  subroutine compute_csl_mat( &
711  interp, &
712  eta_min, &
713  eta_max, &
714  Npts, &
715  output)
716  class(sll_c_interpolator_1d), pointer :: interp
717  sll_real64, intent(in) :: eta_min
718  sll_real64, intent(in) :: eta_max
719  sll_int32, intent(in) :: npts
720  sll_real64, dimension(:), intent(out) :: output
721  sll_int32 :: i
722  !sll_int32 :: j
723  sll_real64, dimension(:), allocatable :: f
724  sll_int32 :: ierr
725  sll_real64 :: a
726  sll_real64 :: b
727  sll_real64 :: delta
728  sll_real64 :: df0
729  sll_real64 :: df1
730  sll_real64 :: w_deriv_left(4)
731  sll_real64 :: w_deriv_right(4)
732  sll_int32 :: n
733  sll_int32 :: ind
734 
735  w_deriv_left = (/-5.5_f64, 9._f64, -4.5_f64, 1._f64/)
736  w_deriv_right = (/-1._f64, 4.5_f64, -9._f64, 5.5_f64/)
737 
738  delta = (eta_max - eta_min)/real(npts - 1, f64)
739 
740  n = npts - 1
741 
742  !we suppose periodic boundary conditions
743  sll_allocate(f(npts), ierr)
744 
745  output(1:n) = 0._f64
746  output(1) = 0.5_f64
747  output(n) = 0.5_f64 !because we have to take a_{-i}
748  !instead of a_i, if we want to perform further fft of a
749 
750  f = 0._f64
751  call interp%compute_interpolants(f)
752  do i = 1, npts - 1
753  f = 0._f64
754  f(i) = 1._f64
755  if (i == 1) then
756  f(npts) = 1._f64
757  end if
758  !we first compute the interpolants
759  !for this basis function f
760  call interp%compute_interpolants(f)
761  !a = eta_min+real(i-1,f64)*delta
762  !b = eta_min+real(i,f64)*delta
763  a = eta_min
764  b = eta_min + delta
765  df0 = compute_quadrature(interp, a, b, w_deriv_left)
766  df1 = compute_quadrature(interp, a, b, w_deriv_right)
767  ind = i !1+modulo(N-i,N)
768  output(ind) = output(ind) + (df0 - df1)/12._f64
769 
770  end do
771  do i = 1, n
772  print *, i, output(i)
773  end do
774 
775  end subroutine compute_csl_mat
776 
777  function compute_quadrature(interp, a, b, w) result(res)
778  class(sll_c_interpolator_1d), pointer :: interp
779  sll_real64, intent(in) :: a
780  sll_real64, intent(in) :: b
781  sll_real64, dimension(4), intent(in) :: w
782  sll_real64 :: res
783  sll_real64 :: eta
784  sll_int32 :: i
785 
786  res = 0._f64
787  do i = 1, 4
788  eta = a + (real(i - 1, f64)/3._f64)*(b - a)
789  res = res + w(i)*interp%interpolate_from_interpolant_value(eta)
790  end do
791 
792  end function compute_quadrature
793 
794  subroutine check_solve_csl_mat( &
795  csl_mat, &
796  csl_mat_init, &
797  N, &
798  fft_buf)
799  sll_real64, dimension(:), intent(in) :: csl_mat
800  sll_real64, dimension(:), intent(in) :: csl_mat_init
801  sll_int32, intent(in) :: n
802  sll_real64, dimension(:), intent(in) :: fft_buf
803  sll_real64, dimension(:), allocatable :: f
804  sll_real64, dimension(:), allocatable :: g
805  sll_real64, dimension(:), allocatable :: h
806  sll_int32 :: ierr
807  sll_real64 :: err
808  sll_int32 :: i
809  sll_int32 :: j
810 
811  sll_allocate(f(n), ierr)
812  sll_allocate(g(n), ierr)
813  sll_allocate(h(n), ierr)
814  err = 0._f64
815 
816  do i = 1, n
817  f = 0._f64
818  f(i) = 1._f64
819  h = f
820  call mult_circulant_mat( &
821  n, &
822  csl_mat, &
823  f, &
824  fft_buf)
825  call circ_mat_mul_direct( &
826  csl_mat_init, &
827  f, &
828  g, &
829  n)
830  err = max(err, maxval(abs(h - g)))
831  print *, '#i='
832  do j = 1, n
833  print *, j, f(j), g(j), h(j)
834  end do
835  end do
836 
837  print *, '#err=', err
838  stop
839 
840  end subroutine check_solve_csl_mat
841 
842  subroutine circ_mat_mul_direct(a, input, output, N)
843  sll_real64, dimension(:), intent(in) :: a
844  sll_real64, dimension(:), intent(in) :: input
845  sll_real64, dimension(:), intent(out) :: output
846  sll_int32, intent(in) :: n
847  sll_int32 :: i
848  sll_int32 :: j
849  sll_int32 :: j2
850  sll_int32 :: ind
851 
852  do i = 1, n
853  output(i) = 0._f64
854  do j = 1, n
855  ind = j!1+modulo(i+j-2,N)
856  j2 = 1 + modulo(n - i + 1, n) !1+modulo(N-j,N)
857  output(i) = output(i) + a(j2)*input(ind)
858  end do
859  end do
860 
861  end subroutine circ_mat_mul_direct
862 
863  !we suppose that compute_interpolant is already done
865  interp, &
866  deriv, &
867  N, &
868  eta_min, &
869  eta_max)
870  class(sll_c_interpolator_1d), pointer :: interp
871  sll_real64, dimension(:, :), intent(out) :: deriv
872  sll_int32, intent(in) :: n
873  sll_real64, intent(in) :: eta_min
874  sll_real64, intent(in) :: eta_max
875  sll_int32 :: i
876  sll_real64 :: w_deriv_left(4)
877  sll_real64 :: w_deriv_right(4)
878  sll_real64 :: a
879  sll_real64 :: b
880  sll_real64 :: delta
881 
882  w_deriv_left = (/-5.5_f64, 9._f64, -4.5_f64, 1._f64/)
883  w_deriv_right = (/-1._f64, 4.5_f64, -9._f64, 5.5_f64/)
884 
885  if (n < 1) then
886  print *, 'N=', n
887  sll_error('compute_node_derivative', 'bad size of N')
888  end if
889 
890  if ((size(deriv, 1) < 2) .or. (size(deriv, 2) < n)) then
891  print *, '#size=', size(deriv)
892  print *, '#expected size=', 2, n
893  sll_error('compute_node_derivative', 'bad size of deriv')
894  end if
895 
896  delta = (eta_max - eta_min)/real(n, f64)
897 
898  do i = 1, n
899  a = eta_min + real(i - 1, f64)*delta
900  b = eta_min + real(i, f64)*delta
901  deriv(1, i) = compute_quadrature(interp, a, b, w_deriv_left)
902  deriv(2, i) = compute_quadrature(interp, a, b, w_deriv_right)
903  end do
904 
905  end subroutine compute_node_derivative_order3
906 
908  interp, &
909  input, &
910  deriv, &
911  charac, &
912  Npts, &
913  eta_min, &
914  eta_max, &
915  output, &
916  csl_degree)
917  class(sll_c_interpolator_1d), pointer :: interp
918  sll_real64, dimension(:), intent(in) :: input
919  sll_real64, dimension(:, :), intent(inout) :: deriv
920  sll_real64, dimension(:), intent(in) :: charac
921  sll_int32, intent(in) :: npts
922  sll_real64, intent(in) :: eta_min
923  sll_real64, intent(in) :: eta_max
924  sll_real64, dimension(:), intent(out) :: output
925  sll_int32, intent(in), optional :: csl_degree
926  sll_real64, dimension(:), allocatable :: output_bsl
927  sll_real64, dimension(:), allocatable :: flux
928  sll_int32, dimension(:), allocatable :: jstar
929  sll_real64, dimension(:), allocatable :: alpha
930  sll_int32 :: ierr
931  sll_real64 :: eta
932  sll_int32 :: i
933  sll_int32 :: ind
934  sll_int32 :: n
935  sll_real64 :: dof(4)
936  sll_real64 :: res
937  sll_real64 :: delta
938  sll_real64 :: err
939  sll_real64, dimension(:), allocatable :: xi
940  sll_real64, dimension(:), allocatable :: fxi
941  sll_real64, dimension(:), allocatable :: xval
942  sll_real64, dimension(:), allocatable :: fval
943  sll_int32 :: ii
944  sll_real64 :: a
945  sll_real64 :: b
946  sll_real64 :: xstarj
947  sll_real64 :: xj
948  sll_real64 :: xstarj1
949  sll_int32 :: i1
950  sll_int32 :: ind1
951  sll_real64, dimension(:), allocatable :: ww_tmp
952  sll_real64, dimension(:), allocatable :: ww
953  sll_int32 :: r
954  sll_int32 :: s
955  sll_int32 :: d
956  sll_int32 :: r1
957  sll_int32 :: s1
958  sll_int32 :: num_gauss_points
959  sll_real64, dimension(:, :), allocatable :: xw
960  !sll_real64 :: val
961 
962  if (present(csl_degree)) then
963  d = csl_degree
964  else
965  d = 3
966  end if
967 
968  r = -d/2
969  s = (d + 1)/2
970 
971  sll_allocate(ww_tmp(r:s - 1), ierr)
972 
973  call compute_csl_ww(ww_tmp, r, s)
974 
975  !print *,'d=',d
976  !print *,'r=,s=',r,s
977  !print *,ww_tmp(r:s-1)
978 
979  r1 = -d/2 + 1
980  s1 = (d + 1)/2
981  sll_allocate(ww(r1:s1), ierr)
982 
983  ww(r1:s1) = ww_tmp(r:s - 1)
984 
985  num_gauss_points = (d + 1)/2
986  sll_allocate(xw(2, num_gauss_points), ierr)
988  num_gauss_points, &
989  0._f64, &
990  1._f64)
991  !print *,'points=',xw(1,:)
992  !print *,'weights=',xw(2,:)
993 
994  !stop
995  !print *,'r1,s1=',r1,s1
996  !print *,ww(r1:s1)
997 
998  !stop
999  sll_allocate(xi(r1:s1), ierr)
1000  sll_allocate(fxi(r1:s1), ierr)
1001  sll_allocate(xval(r1:s1), ierr)
1002  sll_allocate(fval(r1:s1), ierr)
1003  do ii = r1, s1
1004  xval(ii) = real(ii, f64)
1005  end do
1006 
1007  !here is the main work for CSL
1008  !(Jf)(tn+dt,xj) = Jf(tn,xj)+G'(xj)
1009  !with G(x) = F1(tn,H(tn;x,tn+dt))-F1(tn,x)
1010  !we have
1011  !G(xj) = F1(tn,xstarj)-F1(tn,xj)= int(Jf(tn,x),x=xj..xstarj)
1012  !we write G(x) = int(G1(s),s=x-dx/2..x+dx/2)/dx
1013  !so, we get
1014  !G'(xj) = (G1(xj+dx/2)-G1(xj-dx/2))/dx
1015  !and thus the scheme is automatically conservative
1016  !we thus have to compute G1(xj+dx/2)
1017  !we know that
1018  !int(G1(s),s=xk-dx/2..xk+dx/2)/dx = int(Jf(tn,x),x=xk..xstark)
1019  !we first consider the case where the displacement
1020  !is less than a cell
1021  !that is xj <= xstarj < xj+dx
1022  !or xj-dx <=xstarj < xj
1023  !if xj <= xstarj < xj+dx
1024  ! val(ell) = int(G1(s),s=x(j+ell)-dx/2..x(j+ell)+dx/2)/dx =
1025  ! = int(Jf(tn,x),x=x(j+ell)..xstar(j+ell)), ell=-1,0,1,2
1026  ! = (1/6)*(xstar(j+ell)-x(j+ell))
1027  ! *(Jf(tn,x(j+ell))
1028  ! +4Jf(tn,(x(j+ell)+xstar(j+ell))/2)
1029  ! +Jf(tn,xstar(j+ell)))
1030  ! to compute the integral, we use polynomial of degree <= 3
1031  ! on [xjstar, xjstar+dx]
1032  !where xjstar<=xstarj<xjstar+dx
1033  ! we then have G1(xj+dx/2)
1034  ! = (7/12)*(val(0)+val(1))-(1/12)*(val(-1)+val(2))
1035  !
1036  ! -1 val(-1) 0 val(0) 1 val(1) 2 val(2) 3
1037  ! |_________|________|________|_________|
1038  ! -3/2 -1/2 1/2 3/2 5/2
1039  !further step is to generalize for
1040  ! a displacement bigger than one cell
1041  !G(xj) = int(Jf(tn,x),x=xj..xjstar)+int(Jf(tn,x),x=xjstar..xstarj)
1042  !G1(xj+dx/2) = A+G2(x0+dx/2)
1043  !for G2 everything is shifted to xjstar instead of xj
1044  !and A = sum(Jf(tn,xk),k=j+1..jstar), if jstar>j
1045  !and A = -sum(Jf(tn,xk),k=jstar..j-1), if jstar<j
1046  ! so we know
1047  ! int(Jf(tn,x),x=xstarj..xjstar)
1048  ! val(ell) = int(G2(s),s=xell-dx/2..xell+dx/2)/dx =
1049  ! = int(Jf(tn,x),x=x(jstar+ell)..xstar(j+ell)), ell=-1,0,1,2
1050  ! to compute the integral, we use polynomial of degree <= 3
1051  ! on [xjstar, xjstar+dx]
1052  ! we then have G2(x0+dx/2)
1053  ! = (7/12)*(val(0)+val(1))-(1/12)*(val(-1)+val(2))
1054  !
1055  ! -1 val(-1) 0 val(0) 1 val(1) 2 val(2) 3
1056  ! |_________|________|________|_________|
1057  ! -3/2 -1/2 1/2 3/2 5/2
1058  !
1059  !we compute the flux at 1/2 (we take x0=0,dx=1)
1060  !to begin we do a first version that just reproduces BSL
1061  sll_allocate(output_bsl(npts), ierr)
1062  sll_allocate(flux(0:npts), ierr)
1063  sll_allocate(jstar(1 + r1 - 10:npts + s1 + 10), ierr)
1064  sll_allocate(alpha(1 + r1 - 10:npts + s1 + 10), ierr)
1065 
1066  n = npts - 1
1067 
1068  delta = (eta_max - eta_min)/real(n, f64)
1069 
1070  output_bsl = input
1071 
1072  !added; otherwise small diff with bsl
1073  output_bsl(npts) = output_bsl(1)
1074 
1075  call interp%compute_interpolants(output_bsl)
1077  interp, &
1078  deriv, &
1079  npts - 1, &
1080  eta_min, &
1081  eta_max)
1082 
1083  err = 0._f64
1084 
1085  !print *,'r1=',r1,s1
1086  !stop
1087 
1088  do i = 1, npts
1089  eta = charac(i)
1090  eta = sll_f_process_outside_point_periodic(eta, eta_min, eta_max)
1091  eta = real(n, f64)*(eta - eta_min)/(eta_max - eta_min)
1092  ind = floor(eta)
1093  eta = eta - ind
1094  if ((eta < 0) .or. (eta >= 1)) then
1095  print *, 'eta=', eta
1096  sll_error('update_solution_csl_periodic', 'bad value of eta')
1097  end if
1098  if ((ind < 0) .or. (ind >= n)) then
1099  print *, 'ind=', eta
1100  sll_error('update_solution_csl_periodic', 'bad value of ind')
1101  end if
1102  ind = ind + 1
1103  dof(1) = output_bsl(ind)
1104  dof(2) = output_bsl(ind + 1)
1105  dof(3) = deriv(1, ind)
1106  dof(4) = deriv(2, ind)
1107  output(i) = evaluate_hermite_1d(eta, dof)
1108  eta = charac(i)
1109  eta = sll_f_process_outside_point_periodic(eta, eta_min, eta_max)
1110  res = output(i) - interp%interpolate_from_interpolant_value(eta)
1111  if (abs(res) > 1.e-10) then
1112  print *, '#problem detected'
1113  print *, '#dof=', dof
1114  print *, 'ind=', ind
1115  eta = charac(i)
1116  eta = sll_f_process_outside_point_periodic(eta, eta_min, eta_max)
1117  eta = real(n, f64)*(eta - eta_min)/(eta_max - eta_min)
1118  ind = floor(eta)
1119  eta = eta - ind
1120  print *, '#eta=', eta
1121  stop
1122  end if
1123  err = max(err, abs(res))
1124  end do
1125 
1126  !check that the hermite version of bsl
1127  !leads to the same result
1128  if (err > 1.e-14) then
1129  print *, '#err bsl=', err
1130  end if
1131  output_bsl = output
1132  output = output_bsl
1133  output_bsl = input
1134  !now we construct the new scheme
1135 
1136  !do i=1,Npts
1137  ! output_bsl(i) = 1._f64
1138  !enddo
1139 
1140  call interp%compute_interpolants(output_bsl)
1142  interp, &
1143  deriv, &
1144  npts - 1, &
1145  eta_min, &
1146  eta_max)
1147 
1148  !we compute jstar
1149  do i = 1, npts
1150  eta = charac(i)
1151  eta = real(n, f64)*(eta - eta_min)/(eta_max - eta_min)
1152  jstar(i) = floor(eta)
1153  alpha(i) = eta - jstar(i)
1154  jstar(i) = jstar(i) + 1
1155  if ((alpha(i) < 0._f64) .or. (alpha(i) >= 1.)) then
1156  print *, 'alpha(i)=', i, alpha(i)
1157  sll_error('update_solution_csl_periodic', 'bad value of alpha(i)')
1158  end if
1159  !print *,i,jstar(i)-i,jstar(i)
1160  end do
1161  !stop
1162  err = abs(real(jstar(npts) - jstar(1) - n, f64))
1163  err = max(err, abs(alpha(n + 1) - alpha(1)))
1164  if (err > 1.e-13) then
1165  print *, '#err periodicity=', err
1166  end if
1167 
1168  !enforce periodicity
1169  jstar(n + 1) = jstar(1) + n
1170  alpha(n + 1) = alpha(1)
1171 
1172  !boundary conditions
1173  do ii = r1, 0
1174  jstar(ii) = jstar(n + ii) - n
1175  alpha(ii) = alpha(n + ii)
1176  end do
1177  do ii = 1, 1 + s1
1178  jstar(n + ii) = jstar(ii) + n
1179  alpha(n + ii) = alpha(ii)
1180  end do
1181 ! jstar(0) = jstar(N)-N
1182 ! jstar(-1) = jstar(N-1)-N
1183 ! jstar(-2) = jstar(N-2)-N
1184 ! jstar(-3) = jstar(N-3)-N
1185 ! jstar(N+2) = jstar(2)+N
1186 ! jstar(N+3) = jstar(3)+N
1187 ! jstar(N+4) = jstar(4)+N
1188 ! alpha(0) = alpha(N)
1189 ! alpha(-1) = alpha(N-1)
1190 ! alpha(N+2) = alpha(2)
1191 ! alpha(N+3) = alpha(3)
1192 
1193  !we then check that the jstar and alpha
1194  !are well computed
1195 
1196  err = 0._f64
1197  do i = 1, npts
1198  eta = real(jstar(i) - 1, f64) + alpha(i)
1199  eta = eta_min + eta*delta
1200  err = max(err, abs(eta - charac(i)))
1201  end do
1202 
1203  if (err > 1.e-14) then
1204  print *, '#err charac=', err
1205  end if
1206 
1207  !now we try order 3 (?)
1208 
1209  do i = 1, n
1210  !xj = eta_min+real(i-1,f64)*delta
1211  !xstarj = charac(i)
1212  !xstarj = eta_min+(jstar(i)+alpha(i)-1)*delta
1213 
1214  !we now use lagrange interpolation of degree d-1
1215  !for d=4
1216  !-1,0,1,2
1217  !for d=3
1218  !0,1,2
1219  !->r1,s1
1220  !for the moment we use Hermite
1221 
1222  ind = 1 + modulo(n + jstar(i) - 1, n)
1223  ind1 = 1 + modulo(n + jstar(i), n)
1224  dof(1) = output_bsl(ind)
1225  dof(2) = output_bsl(ind1)
1226  dof(3) = deriv(1, ind)
1227  dof(4) = deriv(2, ind)
1228 
1229  do ii = r1, s1
1230  fval(ii) = output_bsl(1 + modulo(n + jstar(i) + ii - 1, n))
1231  end do
1232 
1233  do ii = r1, s1
1234  xi(ii) = jstar(i + ii) + alpha(i + ii) - jstar(i)
1235  end do
1236 
1237  do ii = r1, s1
1238  a = real(ii, f64)
1239  b = xi(ii)
1240  fxi(ii) = contribution_gauss_lagrange( &
1241  a, &
1242  b, &
1243  xval, &
1244  fval, &
1245  r1, &
1246  s1, &
1247  xw, &
1248  num_gauss_points)
1249 ! val = contribution_simpson_hermite(a,b,dof)
1250 ! if(abs(val-fxi(ii))>1.e-12)then
1251 ! print *,fxi(ii),val
1252 ! print *,'a,b=',a,b
1253 ! print *,'dof=',dof
1254 ! print *,'xval=',xval
1255 ! print *,'fval=',fval
1256 ! stop
1257 ! endif
1258  end do
1259 
1260  flux(i) = 0._f64
1261  do ii = r1, s1
1262  flux(i) = flux(i) + ww(ii)*fxi(ii)
1263  end do
1264  !flux(i) = (7._f64/12._f64)*(fxi(0)+fxi(1))
1265  !flux(i) = flux(i)-(1._f64/12._f64)*(fxi(-1)+fxi(2))
1266 
1267  !flux(i) = fxi(0)
1268 
1269  !flux(i) = (37._f64/60._f64)*(fxi(0)+fxi(1))
1270  !flux(i) = flux(i)-(8._f64/60._f64)*(fxi(-1)+fxi(2))
1271  !flux(i) = flux(i)+(1._f64/60._f64)*(fxi(-2)+fxi(3))
1272 
1273  !flux(i) = (6._f64/12._f64)*(fxi(0)+fxi(1))
1274  !flux(i) = flux(i)-(1._f64/12._f64)*(fxi(-1)+fxi(2))
1275 
1276  do ii = i + 1, jstar(i)
1277  ind1 = 1 + modulo(ii + n - 1, n)
1278  flux(i) = flux(i) + output_bsl(ind1)
1279  end do
1280  do ii = jstar(i) + 1, i
1281  ind1 = 1 + modulo(ii + n - 1, n)
1282  flux(i) = flux(i) - output_bsl(ind1)
1283  end do
1284 
1285  end do
1286 
1287  flux(n + 1) = flux(1)
1288 
1289  do i = 1, n
1290  ind1 = 1 + modulo(i - 1 + n - 1, n)
1291  output(i) = output_bsl(i) + (flux(i) - flux(ind1))
1292  end do
1293  output(n + 1) = output(1)
1294 
1295  return
1296 
1297  !we do a first version that is subject to CFL condition
1298  ! this is the simplest scheme that should always work
1299 
1300  do i = 1, npts
1301  xj = eta_min + real(i - 1, f64)*delta
1302  xstarj = charac(i)
1303  if (xstarj .ge. xj) then
1304  if (xstarj .ge. (xj + delta)) then
1305  print *, 'xstarj>=xj+delta'
1306  print *, 'xstarj=', xstarj
1307  print *, 'xj+delta=', xj + delta
1308  print *, 'i=', i
1309  sll_error('update_solution_csl_periodic', 'dt may be too big')
1310  end if
1311  flux(i) = output_bsl(1 + modulo(i, n))*(xstarj - xj)/delta !to begin low order approx
1312  else
1313  if (xstarj .le. (xj - delta)) then
1314  print *, 'xstarj<=xj-delta'
1315  print *, 'xstarj=', xstarj
1316  print *, 'xj-delta=', xj - delta
1317  print *, 'i=', i
1318  sll_error('update_solution_csl_periodic', 'dt may be too big')
1319  end if
1320  flux(i) = output_bsl(i)*(xstarj - xj)/delta
1321  end if
1322  end do
1323 
1324  do i = 1, n
1325  output(i) = output_bsl(i) + (flux(i) - flux(1 + modulo(i - 1 + n - 1, n)))
1326  end do
1327  output(n + 1) = output(1)
1328 
1329  !now we try something of order 1 for the function
1330  !previous version was order 0 for function
1331 
1332  do i = 1, n
1333  xj = eta_min + real(i - 1, f64)*delta
1334  xstarj = charac(i)
1335  if (xstarj .ge. xj) then
1336  if (xstarj .ge. (xj + delta)) then
1337  print *, 'xstarj>=xj+delta'
1338  print *, 'xstarj=', xstarj
1339  print *, 'xj+delta=', xj + delta
1340  print *, 'i=', i
1341  sll_error('update_solution_csl_periodic', 'dt may be too big')
1342  end if
1343  i1 = 1 + modulo(i, n)
1344  a = 0.5_f64*(xj + xstarj)
1345  fxi(0) = output_bsl(i)*(xj + delta - a)/delta
1346  fxi(0) = fxi(0) + output_bsl(i1)*(1._f64 - (xj + delta - a)/delta)
1347  fxi(0) = fxi(0)*(xstarj - xj)/delta
1348  xstarj1 = real(jstar(i + 1) - 1, f64) + alpha(i + 1)
1349  xstarj1 = eta_min + xstarj1*delta
1350  !do not use charac(i1) because charac is not periodic
1351  a = 0.5_f64*(xj + delta + xstarj1)
1352  fxi(1) = output_bsl(i)*(xj + delta - a)/delta
1353  fxi(1) = fxi(1) + output_bsl(i1)*(1._f64 - (xj + delta - a)/delta)
1354  fxi(1) = fxi(1)*(xstarj1 - xj - delta)/delta
1355  flux(i) = 0.5_f64*(fxi(0) + fxi(1))
1356  else
1357  !SLL_ERROR('update_solution_csl_periodic','temporary we do not want this case')
1358  if (xstarj .le. (xj - delta)) then
1359  print *, 'xstarj<=xj-delta'
1360  print *, 'xstarj=', xstarj
1361  print *, 'xj-delta=', xj - delta
1362  print *, 'i=', i
1363  sll_error('update_solution_csl_periodic', 'dt may be too big')
1364  end if
1365  flux(i) = output_bsl(i)*(xstarj - xj)/delta
1366  end if
1367  end do
1368 
1369  flux(n + 1) = flux(1)
1370 
1371  do i = 1, n
1372  output(i) = output_bsl(i) + (flux(i) - flux(1 + modulo(i - 1 + n - 1, n)))
1373  end do
1374  output(n + 1) = output(1)
1375 
1376 !
1377 !
1378 !
1379 ! !if(xstarj.ge.xj)then
1380 ! if(jstar(i).ge.i)then
1381 ! if(jstar(i)>i)then
1382 ! !if(xstarj.ge.(xj+delta))then
1383 ! print *,'xstarj>=xj+delta'
1384 ! print *,'xstarj=',xstarj
1385 ! print *,'xj+delta=',xj+delta
1386 ! print *,'i=',i
1387 ! SLL_ERROR('update_solution_csl_periodic','dt may be too big')
1388 ! endif
1389 ! ind = 1+modulo(N+jstar(i)-1,N)
1390 ! ind1 = 1+modulo(N+jstar(i),N)
1391 ! dof(1) = output_bsl(ind)
1392 ! dof(2) = output_bsl(ind1)
1393 ! dof(3) = deriv(1,ind)
1394 ! dof(4) = deriv(2,ind)
1395 !
1396 ! !we have jstar(i) = i
1397 ! do ii=-1,2
1398 ! !xi(ii) = jstar(i+ii)+alpha(i+ii)-i
1399 ! xi(ii) = jstar(i+ii)+alpha(i+ii)-jstar(i)
1400 ! !print *,'xi(ii)=',ii,xi(ii)
1401 ! enddo
1402 ! !stop
1403 !
1404 ! do ii=-1,2
1405 ! a = real(ii,f64)
1406 ! b = xi(ii)
1407 ! fxi(ii) = contribution_simpson_hermite(a,b,dof)
1408 ! enddo
1409 ! flux(i) = (7._f64/12._f64)*(fxi(0)+fxi(1))
1410 ! flux(i) = flux(i)-(1._f64/12._f64)*(fxi(-1)+fxi(2))
1411 ! !if jstar(i)>i ->+sum(j=i+1..jstar(i))
1412 ! do ii=i+1,jstar(i)
1413 ! ind1 = 1+modulo(ii+N-1,N)
1414 ! flux(i) = flux(i)+output_bsl(ind1)
1415 ! enddo
1416 !
1417 ! else
1418 ! !SLL_ERROR('update_solution_csl_periodic','temporary we do not want this case')
1419 ! if(jstar(i)<i-1)then
1420 ! !if(xstarj.le.(xj-delta))then
1421 ! print *,'xstarj<=xj-delta'
1422 ! print *,'xstarj=',xstarj
1423 ! print *,'xj-delta=',xj-delta
1424 ! print *,'i=',i
1425 ! SLL_ERROR('update_solution_csl_periodic','dt may be too big')
1426 ! endif
1427 !
1428 ! ind = 1+modulo(N+jstar(i)-1,N)
1429 ! ind1 = 1+modulo(N+jstar(i),N)
1430 ! if(ind1.ne.i)then
1431 ! print *,'#ind1 should be equal to i'
1432 ! print *,'#ind1=',ind1
1433 ! print *,'#i=',i
1434 ! print *,'#xstarj=',xstarj
1435 ! print *,'#jstar(i)=',jstar(i)
1436 ! print *,'#alpha(i)=',alpha(i)
1437 ! print *,'#xstarj2=',eta_min+(jstar(i)+alpha(i)-1)*delta
1438 ! SLL_ERROR('update_solution_csl_periodic',"bad value of ind")
1439 ! endif
1440 !
1441 ! dof(1) = output_bsl(ind)
1442 ! dof(2) = output_bsl(ind1)
1443 ! dof(3) = deriv(1,ind)
1444 ! dof(4) = deriv(2,ind)
1445 !
1446 !
1447 ! !we have jstar(i) = i-1
1448 ! do ii=-1,2
1449 ! !xi(ii) = jstar(i+ii)+alpha(i+ii)-i+1
1450 ! xi(ii) = jstar(i+ii)+alpha(i+ii)-jstar(i)
1451 ! !i-jstar(i-ii)-alpha(i-ii)
1452 ! !print *,'xi(ii)=',ii,xi(ii)
1453 ! enddo
1454 ! !stop
1455 ! do ii=-1,2
1456 ! a = real(ii,f64)
1457 ! b = xi(ii)
1458 ! fxi(ii) = contribution_simpson_hermite(a,b,dof)
1459 ! enddo
1460 ! flux(i) = (7._f64/12._f64)*(fxi(0)+fxi(1))
1461 ! flux(i) = flux(i)-(1._f64/12._f64)*(fxi(-1)+fxi(2))
1462 ! !flux(i) = flux(i)-output_bsl(ind1)
1463 ! do ii=jstar(i)+1,i
1464 ! ind1 = 1+modulo(ii+N-1,N)
1465 ! flux(i) = flux(i)-output_bsl(ind1)
1466 ! enddo
1467 ! !ind1 = 1+modulo(N+jstar(i),N)
1468 ! !if jstar(i)=i-2 -> -output_bsl(i)-output_bsl(i-1)
1469 ! !if jstar(i)=i-1 -> -output_bsl(i)
1470 ! !if jstar(i)<i ->-sum(j=jstar(i)+1..i)
1471 ! !if jstar(i)=i -> 0
1472 ! !if jstar(i)>i ->+sum(j=i+1..jstar(i))
1473 ! !if jstar(i)=i+1 ->+output_bsl(i+1)
1474 ! !if jstar(i)=i+2 ->+output_bsl(i+1)+output_bsl(i+2)
1475 !
1476 ! endif
1477 ! enddo
1478 
1479  do i = 1, npts
1480 
1481  ind = 1 + modulo(n + jstar(i) - 1, n)
1482  dof(1) = output_bsl(ind)
1483  dof(2) = output_bsl(ind + 1)
1484  dof(3) = deriv(1, ind)
1485  dof(4) = deriv(2, ind)
1486 
1487  do ii = -1, 2
1488  xi(ii) = jstar(i + ii) + alpha(i + ii) - jstar(i)
1489  end do
1490  do ii = -1, 2
1491  a = real(ii, f64)
1492  b = xi(ii)
1493  fxi(ii) = contribution_simpson_hermite(a, b, dof)
1494  end do
1495  flux(i) = (7._f64/12._f64)*(fxi(0) + fxi(1))
1496  flux(i) = flux(i) - (1._f64/12._f64)*(fxi(-1) + fxi(2))
1497 
1498  !and A = sum(Jf(tn,xk),k=j+1..jstar), if jstar>j
1499  !and A = -sum(Jf(tn,xk),k=jstar..j-1), if jstar<j
1500  do ii = i + 1, jstar(i)
1501  ind = 1 + modulo(n + jstar(ii) - 1, n)
1502  flux(i) = flux(i) + output_bsl(ind)
1503  end do
1504  do ii = jstar(i), i - 1
1505  ind = 1 + modulo(n + jstar(ii) - 1, n)
1506  flux(i) = flux(i) - output_bsl(ind)
1507  end do
1508 
1509  !print *,i,fxi
1510  end do
1511 
1512  flux(0) = flux(n)
1513  do i = 1, n
1514  output(i) = input(i) + (flux(i) - flux(i - 1)) !/delta
1515  end do
1516 
1517  output(n + 1) = output(1)
1518 
1519  err = maxval(abs(output - output_bsl))
1520 
1521  if (err > 1.e-14) then
1522  print *, '#diff with bsl=', err
1523 
1524  do i = 1, npts
1525  print *, i, output(i)
1526  end do
1527  stop
1528  end if
1529 
1530  !output = output_bsl
1531 
1532  !stop
1533 
1534  end subroutine update_solution_csl_periodic
1535 
1536  function evaluate_hermite_1d(x, dof) result(res)
1537  sll_real64, intent(in)::x
1538  sll_real64, dimension(:), intent(in) :: dof
1539  sll_real64 :: res
1540  sll_real64 :: w(4)
1541 
1542  w(1) = (2._f64*x + 1)*(1._f64 - x)*(1._f64 - x)
1543  w(2) = x*x*(3._f64 - 2._f64*x)
1544  w(3) = x*(1._f64 - x)*(1._f64 - x)
1545  w(4) = x*x*(x - 1._f64)
1546  res = dof(1)*w(1) + dof(2)*w(2) + dof(3)*w(3) + dof(4)*w(4)
1547 
1548  end function evaluate_hermite_1d
1549 
1551  a, &
1552  b, &
1553  dof) &
1554  result(res)
1555  sll_real64, intent(in) :: a
1556  sll_real64, intent(in) :: b
1557  sll_real64, dimension(:), intent(in) :: dof
1558  !sll_real64 :: eta
1559  sll_real64 :: res
1560  sll_real64 :: nodes(3, 2)
1561  sll_int32 :: j
1562 
1563  nodes(1, 1) = a
1564  nodes(3, 1) = b
1565  nodes(2, 1) = 0.5_f64*(a + b)
1566  do j = 1, 3
1567  nodes(j, 2) = evaluate_hermite_1d(nodes(j, 1), dof)
1568  end do
1569  res = nodes(1, 2) + 4._f64*nodes(2, 2) + nodes(3, 2)
1570  res = res*(b - a)/6._f64
1571 
1572  end function contribution_simpson_hermite
1573 
1574  subroutine compute_csl_ww(ww, r, s)
1575  sll_int32, intent(in) :: r
1576  sll_int32, intent(in) :: s
1577  sll_real64, dimension(r:s - 1), intent(out) :: ww
1578  sll_real64, dimension(:), allocatable :: w
1579  sll_real64 :: tmp
1580  sll_int32 :: i
1581  sll_int32 :: j
1582  sll_int32 :: ierr
1583 
1584  sll_allocate(w(r:s), ierr)
1585 
1586  ww = 0._f64
1587  do i = r, -1
1588  tmp = 1._f64
1589  do j = r, i - 1
1590  tmp = tmp*real(i - j, f64)
1591  end do
1592  do j = i + 1, s
1593  tmp = tmp*real(i - j, f64)
1594  end do
1595  tmp = 1._f64/tmp
1596  do j = r, i - 1
1597  tmp = tmp*real(-j, f64)
1598  end do
1599  do j = i + 1, -1
1600  tmp = tmp*real(-j, f64)
1601  end do
1602  do j = 1, s
1603  tmp = tmp*real(-j, f64)
1604  end do
1605  w(i) = tmp
1606  end do
1607 
1608  do i = 1, s
1609  tmp = 1._f64
1610  do j = r, i - 1
1611  tmp = tmp*real(i - j, f64)
1612  end do
1613  do j = i + 1, s
1614  tmp = tmp*real(i - j, f64)
1615  end do
1616  tmp = 1._f64/tmp
1617  do j = r, -1
1618  tmp = tmp*real(-j, f64)
1619  end do
1620  do j = 1, i - 1
1621  tmp = tmp*real(-j, f64)
1622  end do
1623  do j = i + 1, s
1624  tmp = tmp*real(-j, f64)
1625  end do
1626  w(i) = tmp
1627  end do
1628 
1629  tmp = 0._f64
1630  do i = r, -1
1631  tmp = tmp + w(i)
1632  end do
1633  do i = 1, s
1634  tmp = tmp + w(i)
1635  end do
1636  w(0) = -tmp
1637 
1638  tmp = 0._f64
1639  do i = r, -1
1640  tmp = tmp + w(i)
1641  ww(i) = -tmp
1642  end do
1643  tmp = 0._f64
1644  do i = s, 1, -1
1645  tmp = tmp + w(i)
1646  ww(i - 1) = tmp
1647  end do
1648 
1649  !print *,'r,s=',r,s
1650  !print *,'w=',w
1651 
1652  !print *,'ww=',ww
1653  !SLL_DEALLOCATE_ARRAY(w,ierr)
1654 
1655  end subroutine compute_csl_ww
1656 
1657  function contribution_gauss_lagrange(a, b, xval, fval, r, s, xw, ng) result(res)
1658  sll_real64, intent(in) :: a
1659  sll_real64, intent(in) :: b
1660  sll_int32, intent(in) :: r
1661  sll_int32, intent(in) :: s
1662  sll_real64, dimension(r:s), intent(in) :: xval
1663  sll_real64, dimension(r:s), intent(in) :: fval
1664  sll_real64, dimension(:, :), intent(in) ::xw
1665  sll_int32, intent(in) :: ng
1666  sll_real64 :: res
1667  sll_int32 :: i
1668  sll_int32 :: d
1669  sll_real64 :: x
1670  !sll_real64 :: nodes(3)
1671 
1672  !print *,'a=',a,b
1673  !print *,'xval=',xval(r:s)
1674  !print *,'r=',r,s
1675  d = s - r
1676  res = 0._f64
1677  !do i=r,s
1678  ! print *,sll_f_lagrange_interpolate(xval(i),d,xval(r:s),fval(r:s))
1679  !enddo
1680  !stop
1681  !x = a
1682  !nodes(1) = sll_f_lagrange_interpolate(x,d,xval(r:s),fval(r:s))
1683  !x = 0.5_f64*(a+b)
1684  !nodes(2) = sll_f_lagrange_interpolate(x,d,xval(r:s),fval(r:s))
1685  !x = b
1686  !nodes(3) = sll_f_lagrange_interpolate(x,d,xval(r:s),fval(r:s))
1687 
1688  !res = nodes(1)+4._f64*nodes(2)+nodes(3)
1689  !res = res*(b-a)/6._f64
1690 
1691  !print *,'res simpson=',res
1692 
1693  res = 0._f64
1694  do i = 1, ng
1695  x = a + xw(1, i)*(b - a)
1696  !print *,'x=',i,x
1697  res = res + (b - a)*xw(2, i)*sll_f_lagrange_interpolate(x, d, xval(r:s), fval(r:s))
1698  end do
1699 
1700  !print *,'res gauss=',res
1701 
1702  end function contribution_gauss_lagrange
1703 
Abstract class for advection.
conservative semi-lagrangian 1d advection using periodic interpolation
subroutine update_solution_csl_periodic(interp, input, deriv, charac, Npts, eta_min, eta_max, output, csl_degree)
real(kind=f64) function contribution_gauss_lagrange(a, b, xval, fval, r, s, xw, ng)
subroutine compute_csl_integral(Npts, interp, origin, feet, output)
real(kind=f64) function compute_quadrature(interp, a, b, w)
subroutine check_solve_csl_mat(csl_mat, csl_mat_init, N, fft_buf)
subroutine mult_circulant_mat(N, mat, f, fft_buf)
type(csl_periodic_1d_advector) function, pointer, public sll_f_new_csl_periodic_1d_advector(interp, charac, Npts, eta_min, eta_max, eta_coords, csl_degree)
subroutine circ_mat_mul_direct(a, input, output, N)
real(kind=f64) function contribution_simpson_hermite(a, b, dof)
subroutine csl_periodic_advect_1d_constant(adv, A, dt, input, output)
subroutine csl_periodic_advect_1d(adv, A, dt, input, output)
subroutine initialize_csl_periodic_1d_advector(adv, interp, charac, Npts, eta_min, eta_max, eta_coords, csl_degree)
real(kind=f64) function evaluate_hermite_1d(x, dof)
subroutine check_charac_feet(origin, feet, Npts, epsilon)
subroutine compute_csl_mat(interp, eta_min, eta_max, Npts, output)
real(kind=f64) function compute_gap_min(input, Npts)
real(kind=f64) function compute_gap_max(input, Npts)
subroutine compute_node_derivative_order3(interp, deriv, N, eta_min, eta_max)
real(kind=f64) function compute_simpson_contribution_csl_periodic(interp, a, b, eta_min, eta_max)
Abstract class for characteristic derived type.
function, public sll_f_process_outside_point_periodic(eta, eta_min, eta_max)
real(kind=f64) function, dimension(2, 1:npoints), public sll_f_gauss_legendre_points_and_weights(npoints, a, b)
Returns a 2d array of size (2,npoints) containing gauss-legendre points and weights in the interval [...
subroutine, public sll_s_compute_w_hermite_1d(w, r, s)
Module for 1D interpolation and reconstruction.
real(kind=f64) function, public sll_f_lagrange_interpolate(x, degree, xi, yi)
Abstract class for 1D interpolation and reconstruction.
    Report Typos and Errors