Report Typos and Errors    
Semi-Lagrangian Library
Modular library for kinetic and gyrokinetic simulations of plasmas in fusion energy devices.
sll_m_box_splines.F90
Go to the documentation of this file.
1 
10 
12 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13 #include "sll_memory.h"
14 #include "sll_working_precision.h"
15 
17  sll_p_dirichlet, &
18  sll_p_neumann, &
19  sll_p_periodic
20 
21  use sll_m_constants, only: &
24 
25  use sll_m_hex_pre_filters, only: &
30 
31  use sll_m_hexagonal_meshes, only: &
36  sll_o_delete, &
42 
43  use sll_m_utilities, only: &
45 
46  implicit none
47 
48  public :: &
56  sll_o_delete, &
58 
59  private
60 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
61 
68  type(sll_t_hex_mesh_2d), pointer :: mesh
69  sll_int32, private :: bc_type
70  sll_real64, dimension(:), pointer :: coeffs
71 
72  contains
73  procedure, pass(spline) :: compute_coeff_box_spline_2d
74  procedure, pass(spline) :: compute_coeff_box_spline_2d_diri
75  procedure, pass(spline) :: compute_coeff_box_spline_2d_prdc
76  procedure, pass(spline) :: compute_coeff_box_spline_2d_neum
77  end type sll_t_box_spline_2d
78 
82  interface sll_o_delete
83  module procedure delete_box_spline_2d
84  end interface sll_o_delete
85 
86 contains ! ****************************************************************
87 
88 #define MAKE_GET_SLOT_FUNCTION( fname, datatype, slot, ret_type ) \
89  function fname(spline_obj) result(val); \
90  type(datatype), pointer :: spline_obj; \
91  ret_type :: val; \
92  val = spline_obj%slot; \
93  end function fname
94 
95  !---------------------------------------------------------------------------
104  mesh, &
105  bc_type)
106 
108  type(sll_t_hex_mesh_2d), pointer :: mesh
109  sll_int32, intent(in) :: bc_type
110  sll_int32 :: ierr
111 
112  sll_allocate(sll_f_new_box_spline_2d, ierr)
113 
114  sll_f_new_box_spline_2d%mesh => mesh
115 
116  sll_f_new_box_spline_2d%bc_type = bc_type
117 
118  sll_allocate(sll_f_new_box_spline_2d%coeffs(1:mesh%num_pts_tot), ierr)
119 
120  end function sll_f_new_box_spline_2d
121 
122  !---------------------------------------------------------------------------
129  subroutine compute_coeff_box_spline_2d(spline, data, deg)
130  class(sll_t_box_spline_2d), intent(inout) :: spline
131  sll_real64, dimension(:), target, intent(in) :: data
132  sll_int32, intent(in) :: deg
133 
134  ! We make every case explicit to facilitate adding more BC types in
135  ! the future.
136  select case (spline%bc_type)
137  case (sll_p_dirichlet)
138  ! boundary condition type is dirichlet
139  call spline%compute_coeff_box_spline_2d_diri(data, deg)
140  case (sll_p_periodic)
141  ! boundary condition type is periodic
142  call spline%compute_coeff_box_spline_2d_prdc(data, deg)
143  case (sll_p_neumann)
144  ! boundary condition type is neumann
145  call spline%compute_coeff_box_spline_2d_neum(data, deg)
146  case default
147  print *, 'ERROR: compute_coeff_box_spline_2d(): ', &
148  'did not recognize given boundary condition combination.'
149  stop
150  end select
151 
152  end subroutine compute_coeff_box_spline_2d
153 
154  !---------------------------------------------------------------------------
161  subroutine compute_coeff_box_spline_2d_diri(spline, data, deg)
162  class(sll_t_box_spline_2d), intent(inout) :: spline
163  sll_real64, dimension(:), intent(in), target :: data ! data to be fit
164  sll_int32, intent(in) :: deg
165 
166  sll_int32 :: num_pts_tot
167  sll_int32 :: k1_ref, k2_ref
168  sll_int32 :: k
169  sll_int32 :: i
170  sll_int32 :: ierr
171  sll_int32 :: nei
172  sll_int32 :: num_pts_radius
173  sll_real64 :: filter
174  sll_real64, allocatable, dimension(:) :: filter_array
175 
176  num_pts_tot = spline%mesh%num_pts_tot
177  ! we will work on a radius of 'deg' cells
178  ! we compute the number of total points on that radius
179  num_pts_radius = 3*deg*(deg + 1) + 1
180 
181  ! Create a table for the filter values and fill it:
182 
183  ! TODO: this should be controlled some other way........ sorry.
184  call sll_s_pre_filter_pfir(spline%mesh, deg, filter_array)
185  ! If pINT, pIIR1 or pIIR2:
186  ! SLL_ALLOCATE(filter_array(num_pts_radius), ierr)
187  ! do k=1, num_pts_radius
188  ! ! filter_array(k) = sll_f_pre_filter_int(spline%mesh, k, deg)
189  ! ! filter_array(k) = sll_f_pre_filter_piir1(spline%mesh, k, deg)
190  ! ! filter_array(k) = sll_f_pre_filter_piir2(spline%mesh, k, deg)
191  ! end do
192 
193  do i = 1, num_pts_tot
194 
195  spline%coeffs(i) = real(0, f64)
196  k1_ref = spline%mesh%global_to_hex1(i)
197  k2_ref = spline%mesh%global_to_hex2(i)
198 
199  ! We don't need to fo through all points, just till a certain radius
200  ! which depends on the degree of the spline we are evaluating
201  do k = 1, num_pts_radius
202  filter = filter_array(k)
203  nei = spline%mesh%local_hex_to_global(k1_ref, k2_ref, k)
204  if ((nei .le. num_pts_tot) .and. (nei .gt. 0)) then
205  spline%coeffs(i) = spline%coeffs(i) + data(nei)*filter
206  else
207  ! Boundary conditions (BC) to be treated here :
208  ! With dirichlet boundary conditions data(out_of_domain) = 0
209  spline%coeffs(i) = spline%coeffs(i)
210  end if
211  end do
212  end do
213 
214  end subroutine compute_coeff_box_spline_2d_diri
215 
216  !---------------------------------------------------------------------------
223  subroutine compute_coeff_box_spline_2d_prdc(spline, data, deg)
224  class(sll_t_box_spline_2d), intent(inout) :: spline
225  sll_int32, intent(in) :: deg
226  sll_real64, dimension(:), intent(in), target :: data ! data to be fit
227 
228  sll_int32 :: num_pts_tot
229  sll_int32 :: i
230 
231  print *, ' WARNING : BOUNDARY CONDITIONS PERIODIC NOT &
232  & YET IMPLEMENTED', deg
233  num_pts_tot = spline%mesh%num_pts_tot
234  do i = 1, num_pts_tot
235  spline%coeffs(i) = real(0, f64)*data(i)
236  end do
237 
238  end subroutine compute_coeff_box_spline_2d_prdc
239 
240  !---------------------------------------------------------------------------
247  subroutine compute_coeff_box_spline_2d_neum(spline, data, deg)
248  class(sll_t_box_spline_2d), intent(inout) :: spline
249  sll_real64, dimension(:), intent(in), target :: data ! data to be fit
250  sll_int32, intent(in) :: deg
251 
252  sll_int32 :: num_pts_tot
253  sll_int32 :: i
254 
255  print *, ' WARNING : BOUNDARY CONDITIONS PERIODIC NOT &
256  & YET IMPLEMENTED', deg
257  num_pts_tot = spline%mesh%num_pts_tot
258  do i = 1, num_pts_tot
259  spline%coeffs(i) = real(0, f64)*data(i)
260  end do
261 
262  end subroutine compute_coeff_box_spline_2d_neum
263 
264  !---------------------------------------------------------------------------
270  function choose(n, k) result(res)
271  sll_int32, intent(in) :: n
272  sll_int32, intent(in) :: k
273  sll_real64 :: res
274  if (k .lt. 0) then
275  res = 0._f64
276  else if (n .lt. k) then
277  res = 0._f64
278  else
279  res = real(sll_o_factorial(n), f64)/real((sll_o_factorial(k) &
280  *sll_o_factorial(n - k)), f64)
281  end if
282  end function choose
283 
284  !---------------------------------------------------------------------------
298  function chi_gen_val(x1_in, x2_in, deg) result(val)
299  sll_real64, intent(in) :: x1_in
300  sll_real64, intent(in) :: x2_in
301  sll_int32, intent(in) :: deg
302  sll_real64 :: x1
303  sll_real64 :: x2
304  sll_real64 :: val
305  sll_real64 :: u
306  sll_real64 :: v
307  sll_real64 :: aux
308  sll_real64 :: aux2
309  sll_real64 :: coeff
310  sll_real64 :: g
311  sll_int32 :: k
312  sll_int32 :: l
313  sll_int32 :: i
314  sll_int32 :: d
315 
316  if (deg .ne. 2) then
317  ! ------------------------------------------------
318  ! FOR ARBITRARY ORDER SPLINES :
319  ! We take advantage of the fact that the mesh is symetrical
320  ! So we constrain the points to the first triangles by
321  ! using the symmetry properties
322  ! ------------------------------------------------
323  ! Transformation to hexagonal coordinates :
324  x1 = -abs(x1_in)
325  x2 = abs(x2_in)
326  u = x1 - x2/sll_p_sqrt3
327  v = x1 + x2/sll_p_sqrt3
328  ! First generating vector (r1') symmetry
329  if (v .gt. 0) then
330  v = -v
331  u = u + v
332  end if
333  ! First triangle axe (r2'+r3') symmetry
334  if (v .gt. u/2) then
335  v = u - v
336  end if
337 
338  val = 0._f64
339  do k = -deg, ceiling(u) - 1
340  if ((x1_in .eq. 0._f64) .and. (x2_in .eq. 0.8_f64)) then
341  ! print *, " K = ", K
342  end if
343  do l = -deg, ceiling(v) - 1
344  if ((x1_in .eq. 0._f64) .and. (x2_in .eq. 0.8_f64)) then
345  ! print *, " L = ", L
346  end if
347  do i = 0, min(deg + k, deg + l)
348  if ((x1_in .eq. 0._f64) .and. (x2_in .eq. 0.8_f64)) then
349  ! print *, " i = ", i
350  end if
351  coeff = (-1.0_f64)**(k + l + i)* &
352  choose(deg, i - k)* &
353  choose(deg, i - l)* &
354  choose(deg, i)
355  if ((x1_in .eq. 0._f64) .and. (x2_in .eq. 0.8_f64)) then
356  ! print *, " coeff = ", coeff
357  end if
358  do d = 0, deg - 1
359  if ((x1_in .eq. 0._f64) .and. (x2_in .eq. 0.8_f64)) then
360  ! print *, " d = ", d
361  end if
362  aux = abs(v - real(l, f64) - u + real(k, f64))
363  aux2 = (u - real(k, f64) + v - real(l, f64) - aux)/2._f64
364  if (aux2 .lt. 0._f64) then
365  aux2 = 0._f64
366  end if
367  val = val + coeff*choose(deg - 1 + d, d) &
368  /real(sll_o_factorial(2*deg - 1 + d), f64) &
369  /real(sll_o_factorial(deg - 1 - d), f64) &
370  *aux**(deg - 1 - d) &
371  *aux2**(2*deg - 1 + d)
372  if ((x1_in .eq. 0._f64) .and. (x2_in .eq. 0.8_f64)) then
373  ! print *, " aux, aux2, val = ", aux, aux2, val
374  end if
375  end do
376  end do
377  end do
378  end do
379 
380  else
381  ! ------------------------------------------------
382  ! OPTIMIZED ALGORITHM FOR DEGREE TWO SPLINES :
383  ! We take advantage of the fact that the mesh is symetrical
384  ! So we constrain the points to the first triangles by
385  ! using the symmetry properties
386  ! ------------------------------------------------
387  ! Transformation to hexagonal coordinates :
388  x1 = abs(x1_in)
389  x2 = abs(x2_in)
390  u = x1 - x2/sll_p_sqrt3
391  v = x1 + x2/sll_p_sqrt3
392  if (u .lt. 0) then
393  !Symmetry r2
394  u = -u
395  v = v + u
396  end if
397  if (u .lt. v/2) then
398  !Symmetry r2+r3
399  u = v - u
400  end if
401  g = u - v/2._f64
402  if (v .gt. 2._f64) then
403  val = 0._f64
404  else if (v .lt. 1._f64) then
405  val = 0.5_f64 + &
406  ((5._f64/3._f64 - v/8.0_f64)*v - 3.0_f64)*v*v/4.0_f64 + &
407  ((1._f64 - v/4._f64)*v + g*g/6._f64 - 1._f64)*g*g
408  else if (u .gt. 1._f64) then
409  val = (v - 2._f64)*(v - 2._f64)*(v - 2._f64)*(g - 1._f64)/6.0_f64
410  else
411  val = 5._f64/6._f64 + &
412  ((1._f64 + (1._f64/3._f64 - v/8._f64)*v)*v/4._f64 - 1._f64)*v + &
413  ((1._f64 - v/4._f64)*v + g*g/6.0_f64 - 1._f64)*g*g
414  end if
415  end if
416 
417  end function chi_gen_val
418 
419  !---------------------------------------------------------------------------
428  function sll_f_compute_box_spline(spline, x1, x2, deg) result(val)
429  type(sll_t_box_spline_2d), pointer, intent(in):: spline
430  sll_real64, intent(in) :: x1
431  sll_real64, intent(in) :: x2
432  sll_int32, intent(in) :: deg
433  sll_real64 :: val
434  sll_real64 :: x1_basis
435  sll_real64 :: x2_basis
436 
437  x1_basis = change_basis_x1(spline, x1, x2)
438  x2_basis = change_basis_x2(spline, x1, x2)
439 
440  val = chi_gen_val(x1_basis, x2_basis, deg)
441 
442  end function sll_f_compute_box_spline
443 
444  !---------------------------------------------------------------------------
452  function change_basis_x1(spline, x1, x2) result(x1_basis)
453  type(sll_t_box_spline_2d), pointer :: spline
454  sll_real64, intent(in) :: x1
455  sll_real64, intent(in) :: x2
456  sll_real64 :: delta_q
457  sll_real64 :: k1_basis
458  sll_real64 :: k2_basis
459  sll_real64 :: x1_basis
460  sll_real64 :: inv_delta_q
461  sll_real64 :: q11, q12
462  sll_real64 :: q21, q22
463  sll_real64 :: r11, r12
464  sll_real64 :: r21, r22
465 
466  ! Algorithms basis
467  r11 = 0.5_f64
468  r12 = -sll_p_sqrt3*0.5_f64
469  r21 = r11
470  r22 = -r12
471 
472  ! Getting mesh generator vectors coordinates
473  q11 = spline%mesh%r1_x1
474  q12 = spline%mesh%r1_x2
475  q21 = spline%mesh%r2_x1
476  q22 = spline%mesh%r2_x2
477 
478  !change of basis :
479  delta_q = q11*q22 - q12*q21
480  inv_delta_q = 1._f64/delta_q
481  k1_basis = inv_delta_q*(q22*x1 - q21*x2)
482  k2_basis = inv_delta_q*(q11*x2 - q12*x1)
483  x1_basis = r11*k1_basis + r21*k2_basis
484  end function change_basis_x1
485 
486  !---------------------------------------------------------------------------
494  function change_basis_x2(spline, x1, x2) result(x2_basis)
495  ! This function allows to change a point of coordinates (x1, x2)
496  ! on the spline basis to the mesh basis
497  type(sll_t_box_spline_2d), pointer :: spline
498  sll_real64, intent(in) :: x1
499  sll_real64, intent(in) :: x2
500  sll_real64 :: delta_q
501  sll_real64 :: inv_delta_q
502  sll_real64 :: k1_basis
503  sll_real64 :: k2_basis
504  sll_real64 :: x2_basis
505  sll_real64 :: q11, q12
506  sll_real64 :: q21, q22
507  sll_real64 :: r11, r12
508  sll_real64 :: r21, r22
509 
510  ! Getting spline generator vectors coordinates
511  ! Algorithms basis
512  r11 = 0.5_f64
513  r12 = -0.5_f64*sll_p_sqrt3
514  r21 = r11
515  r22 = -r12
516 
517  ! Getting mesh generator vectors coordinates
518  q11 = spline%mesh%r1_x1
519  q12 = spline%mesh%r1_x2
520  q21 = spline%mesh%r2_x1
521  q22 = spline%mesh%r2_x2
522 
523  !change of basis :
524  delta_q = q11*q22 - q12*q21
525  inv_delta_q = 1._f64/delta_q
526  k1_basis = inv_delta_q*(q22*x1 - q21*x2)
527  k2_basis = inv_delta_q*(q11*x2 - q12*x1)
528  x2_basis = r12*k1_basis + r22*k2_basis
529 
530  end function change_basis_x2
531 
532  !---------------------------------------------------------------------------
542  function sll_f_hex_interpolate_value(mesh_geom, x1, x2, spline, deg) result(val)
543  type(sll_t_hex_mesh_2d), pointer, intent(in) :: mesh_geom
544  type(sll_t_box_spline_2d), pointer :: spline
545  sll_int32, intent(in) :: deg
546  sll_real64, intent(in) :: x1, x2
547  sll_real64 :: xm1, xm2
548  sll_real64 :: x1_spl, x2_spl
549  sll_real64 :: r11, r12
550  sll_real64 :: r21, r22
551  sll_real64 :: r31, r32
552  sll_int32 :: k1_asso, k2_asso
553  sll_int32 :: k1, k2
554  sll_int32 :: ki, kj
555  sll_int32 :: num_pts_tot
556  sll_int32 :: num_cells
557  sll_int32 :: distance
558  sll_int32 :: ind
559  sll_real64 :: val
560 
561  val = 0._f64
562 
563  r11 = mesh_geom%r1_x1
564  r12 = mesh_geom%r1_x2
565  r21 = mesh_geom%r2_x1
566  r22 = mesh_geom%r2_x2
567  r31 = mesh_geom%r3_x1
568  r32 = mesh_geom%r3_x2
569 
570  num_pts_tot = mesh_geom%num_pts_tot
571  num_cells = spline%mesh%num_cells
572 
573  ! First we need to compute the coordinates of
574  ! the closest mesh point associated to (x1,x2)
575  k1_asso = sll_f_cart_to_hex1(mesh_geom, x1, x2)
576  k2_asso = sll_f_cart_to_hex2(mesh_geom, x1, x2)
577 
578  ! Then we will do a loop for all the points
579  ! on the envelopping rhomboid of radius=deg
580  do ki = 1 - deg, deg
581  do kj = 1 - deg, deg
582 
583  k1 = k1_asso + ki
584  k2 = k2_asso + kj
585  distance = sll_f_cells_to_origin(k1, k2)
586 
587  ! We test if we are in the domain
588  if (distance .le. num_cells) then
589 
590  ind = spline%mesh%hex_to_global(k1, k2)
591 
592  ! We centralize and shift the coordinates
593  ! i.e. centralize : xm = x - Rk
594  ! shifting : xm to the associated rhomboid point
595  xm1 = x1 - r11*real(k1_asso, f64) - r21*real(k2_asso, f64) &
596  - real(ki, f64)*r11 - real(kj, f64)*r21
597  xm2 = x2 - r12*real(k1_asso, f64) - r22*real(k2_asso, f64) &
598  - real(ki, f64)*r12 - real(kj, f64)*r22
599 
600  ! change of basis : geometrical basis => spline basis
601  x1_spl = change_basis_x1(spline, xm1, xm2)
602  x2_spl = change_basis_x2(spline, xm1, xm2)
603 
604  val = val + spline%coeffs(ind)* &
605  chi_gen_val(x1_spl, x2_spl, deg)
606  else
607  !! TREAT HERE BC
608  ! TODO @LM
609  if (spline%bc_type .eq. sll_p_dirichlet) then
610  val = val !no update
611  ind = spline%mesh%hex_to_global(k1_asso, k2_asso)
612  else
613  print *, "Error : Boundary condition type not yet implemented"
614  stop
615  end if
616  end if
617  end do
618  end do
619  end function sll_f_hex_interpolate_value
620 
621  !---------------------------------------------------------
632  function non_zeros_splines(mesh, cell_index, deg) result(index_nZ)
633  type(sll_t_hex_mesh_2d), pointer, intent(in) :: mesh
634  sll_int32, intent(in) :: deg
635  sll_int32, intent(in) :: cell_index
636  sll_int32 :: index_nz(3*deg*deg)
637  !sll_int32 :: ierr
638  sll_int32 :: nei_point
639  sll_int32 :: non_zero
640  sll_int32 :: distance
641  sll_int32 :: edge1, edge2, edge3
642  sll_int32 :: first
643  sll_int32 :: last
644  sll_int32 :: type
645  sll_int32 :: i, j
646  sll_int32 :: last_point
647  sll_int32 :: current_nz
648 
649  ! Number of non zero splines on a cell:
650  non_zero = 3*deg*deg
651  index_nz(1:non_zero) = -1
652 
653  !type of cell
654  call mesh%cell_type(cell_index, type)
655 
656  !Getting the cell vertices which are the 1st indices of the non null splines
657  call sll_s_get_cell_vertices_index(mesh%center_cartesian_coord(1, cell_index), &
658  mesh%center_cartesian_coord(2, cell_index), &
659  mesh, &
660  edge1, edge2, edge3)
661 
662  ! index_nZ(1) = edge1
663  ! index_nZ(2) = edge2
664  ! index_nZ(3) = edge3
665 
666  if (type .eq. 2) then
667  index_nz(1) = edge1
668  index_nz(2) = edge2
669  index_nz(3) = edge3
670  else
671  index_nz(1) = edge1
672  index_nz(2) = edge3
673  index_nz(3) = edge2
674  end if
675 
676  current_nz = 4
677  do distance = 1, deg - 1
678  first = 1 + (distance - 1)*(distance - 1)*3
679  last = distance*distance*3
680  do i = first, last
681  last_point = index_nz(i)
682  if (last_point .eq. -1) then
683  print *, "ERROR in non_zero_splines: wrong index, i=", i
684  end if
685  do j = 2, 7 ! this represents the direct neighbours for a point
686  nei_point = sll_f_local_to_global(mesh, last_point, j)
687  if ((nei_point .ne. -1) .and. (.not. (any(index_nz == nei_point)))) then
688  index_nz(current_nz) = nei_point
689  current_nz = current_nz + 1
690  end if
691  end do
692  end do
693  end do
694  end function non_zeros_splines
695 
696  !---------------------------------------------------------------------------
703  function sll_f_boxspline_x1_derivative(x1, x2, deg) result(val)
704  sll_int32, intent(in) :: deg
705  sll_real64, intent(in) :: x1
706  sll_real64, intent(in) :: x2
707  sll_real64 :: h
708  sll_real64 :: fm2h
709  sll_real64 :: fm1h
710  sll_real64 :: fp1h
711  sll_real64 :: fp2h
712  sll_real64 :: val
713 
714  !Computing step on each direction
715  h = max(10._f64*sll_p_epsilon_0*abs(x1), sll_p_epsilon_0)
716 
717  ! Finite difference method of order 5
718  fm2h = chi_gen_val(x1 - 2.0_f64*h, x2, deg)
719  fm1h = chi_gen_val(x1 - h, x2, deg)
720  fp2h = chi_gen_val(x1 + 2.0_f64*h, x2, deg)
721  fp1h = chi_gen_val(x1 + h, x2, deg)
722 
723  val = (-fp2h + 8._f64*fp1h - 8._f64*fm1h + fm2h)/12._f64/h
724 
725  end function sll_f_boxspline_x1_derivative
726 
727  !---------------------------------------------------------------------------
734  function sll_f_boxspline_x2_derivative(x1, x2, deg) result(val)
735  sll_int32, intent(in) :: deg
736  sll_real64, intent(in) :: x1
737  sll_real64, intent(in) :: x2
738  sll_real64 :: h
739  sll_real64 :: fm2h
740  sll_real64 :: fm1h
741  sll_real64 :: fp1h
742  sll_real64 :: fp2h
743  sll_real64 :: val
744 
745  !Computing step on each direction
746  h = max(10._f64*sll_p_epsilon_0*abs(x2), sll_p_epsilon_0)
747 
748  ! Finite difference method of order 5
749  fm2h = chi_gen_val(x1, x2 - 2.0_f64*h, deg)
750  fm1h = chi_gen_val(x1, x2 - h, deg)
751  fp2h = chi_gen_val(x1, x2 + 2.0_f64*h, deg)
752  fp1h = chi_gen_val(x1, x2 + h, deg)
753 
754  val = 0.25_f64/3._f64/h*(-fp2h + 8._f64*fp1h - 8._f64*fm1h + fm2h)
755 
756  end function sll_f_boxspline_x2_derivative
757 
758  !---------------------------------------------------------------------------
768  function sll_f_boxspline_val_der(x1, x2, deg, nderiv1, nderiv2) result(val)
769  sll_int32, intent(in) :: deg
770  sll_int32, intent(in) :: nderiv1
771  sll_int32, intent(in) :: nderiv2
772  sll_real64, intent(in) :: x1
773  sll_real64, intent(in) :: x2
774  sll_real64 :: val
775  sll_real64 :: x1_basis
776  sll_real64 :: x2_basis
777  sll_int32 :: ierr
778  type(sll_t_hex_mesh_2d), pointer :: mesh
779  type(sll_t_box_spline_2d), pointer :: spline
780 
781  mesh => sll_f_new_hex_mesh_2d(1)
782  spline => sll_f_new_box_spline_2d(mesh, sll_p_dirichlet)
783  x1_basis = change_basis_x1(spline, x1, x2)
784  x2_basis = change_basis_x2(spline, x1, x2)
785 
786  val = 0._f64
787 
788  if (nderiv1 .eq. 0) then
789  if (nderiv2 .eq. 0) then
791  val = chi_gen_val(x1_basis, x2_basis, deg)
792  else if (nderiv2 .eq. 1) then
794  val = sll_f_boxspline_x2_derivative(x1_basis, x2_basis, deg)
795  else
796  print *, "Error in sll_f_boxspline_val_der : cannot compute this derivative"
797  end if
798  else if (nderiv1 .eq. 1) then
799  ! derivative with respecto to the first coo
800  if (nderiv2 .eq. 0) then
801  val = sll_f_boxspline_x1_derivative(x1_basis, x2_basis, deg)
802  else
803  print *, "Error in sll_f_boxspline_val_der : cannot compute this derivative"
804  end if
805  end if
806 
807  sll_deallocate_array(spline%coeffs, ierr)
808  sll_deallocate(spline, ierr)
809  call sll_o_delete(mesh)
810  end function sll_f_boxspline_val_der
811 
812  !---------------------------------------------------------------------------
819  subroutine sll_s_write_connectivity(mesh, deg)
820  type(sll_t_hex_mesh_2d), pointer :: mesh
821  sll_int32, intent(in) :: deg
822  sll_int32 :: out_unit
823  character(len=28), parameter :: name = "boxsplines_connectivity.txt"
824  sll_int32 :: nz_indices(3*deg*deg)
825  sll_int32 :: num_ele
826  !sll_int32 :: ele_contained
827  sll_int32 :: non_zero
828  !sll_int32 :: ierr
829  sll_int32 :: i
830  !sll_int32 :: s2
831  !sll_int32 :: s3
832  !sll_int32 :: dist
833  sll_int32 :: val
834 
835  ! Number of non Zero splines depends on the degree
836  non_zero = 3*deg*deg
837 
838  ! We open file
839  open (file=name, status="replace", form="formatted", newunit=out_unit)
840 
841  ! We write total number of cells
842  write (out_unit, "(i6)") mesh%num_triangles
843 
844  do num_ele = 1, mesh%num_triangles
845  ! We write cell ID number
846  write (out_unit, "(i6)") sll_f_change_elements_notation(mesh, num_ele)
847  ! We write number of non zero
848  write (out_unit, "(i6)") non_zero
849  ! We write the indices of the non zero splines
850  nz_indices = non_zeros_splines(mesh, num_ele, deg)
851  do i = 1, non_zero
852  val = nz_indices(i)
853  write (out_unit, "(i6)", advance="no") val
854  write (out_unit, "(a)", advance="no") ","
855  end do
856  write (out_unit, "(a)") ""
857  end do
858 
859  close (out_unit)
860 
861  end subroutine sll_s_write_connectivity
862 
866  subroutine delete_box_spline_2d(spline)
867  type(sll_t_box_spline_2d), intent(inout), pointer :: spline
868  sll_int32 :: ierr
869 
870  if (.not. associated(spline)) then
871  print *, 'delete_box_spline_2D(): passed spline is not associated'
872  stop
873  end if
874  call sll_o_delete(spline%mesh)
875  sll_deallocate(spline%coeffs, ierr)
876  sll_deallocate(spline, ierr)
877  end subroutine delete_box_spline_2d
878 
879 end module sll_m_box_splines
Generic sub-routine defined for 2D box spline types. Deallocates the memory associated with the given...
Provides capabilities for values and derivatives interpolation with box splines on hexagonal meshes.
subroutine, public sll_s_write_connectivity(mesh, deg)
Writes connectivity for CAID / DJANGO.
real(kind=f64) function, public sll_f_boxspline_val_der(x1, x2, deg, nderiv1, nderiv2)
Computes the values or derivatives of box splines.
real(kind=f64) function change_basis_x2(spline, x1, x2)
2nd coo. of (x1, x2) in reference hex-mesh coo.
real(kind=f64) function, public sll_f_hex_interpolate_value(mesh_geom, x1, x2, spline, deg)
Interpolates on point of cartesian coordinates (x1, x2)
function chi_gen_val(x1_in, x2_in, deg)
Computes the box spline of degree deg on (x1, x2)
real(kind=f64) function change_basis_x1(spline, x1, x2)
1st coo. of (x1, x2) in reference hex-mesh coo.
subroutine compute_coeff_box_spline_2d_diri(spline, data, deg)
Computes box splines coefficients for dirichlet BC.
subroutine delete_box_spline_2d(spline)
Generic sub-routine defined for 2D box spline types. Deallocates the memory associated with the given...
subroutine compute_coeff_box_spline_2d_prdc(spline, data, deg)
Computes box splines coefficients with periodic BC.
subroutine compute_coeff_box_spline_2d(spline, data, deg)
Computes box splines coefficients.
subroutine compute_coeff_box_spline_2d_neum(spline, data, deg)
Computes box splines coefficients with neumann BC.
integer(kind=i32) function, dimension(3 *deg *deg) non_zeros_splines(mesh, cell_index, deg)
Computes indices of non null splines on a given cell.
function choose(n, k)
Computes the binomial coefficient (n, k)
real(kind=f64) function, public sll_f_boxspline_x2_derivative(x1, x2, deg)
Computes y-derivative on (x,y)
type(sll_t_box_spline_2d) function, pointer, public sll_f_new_box_spline_2d(mesh, bc_type)
Creates a box spline element.
real(kind=f64) function, public sll_f_compute_box_spline(spline, x1, x2, deg)
Computes the value of a box spline.
real(kind=f64) function, public sll_f_boxspline_x1_derivative(x1, x2, deg)
Computes x-derivative on (x,y)
Fortran module where set some physical and mathematical constants.
real(kind=f64), parameter, public sll_p_sqrt3
real(kind=f64), parameter, public sll_p_epsilon_0
Pre-filter for box-splines quasi interpolation.
subroutine, public sll_s_pre_filter_pfir(mesh, deg, weight_tab)
Pre-filter PFIR to compute the box splines coefficients.
real(kind=f64) function, public sll_f_pre_filter_piir2(mesh, local_index, deg)
Pre-filter PIIR2 to compute the box splines coefficients.
real(kind=f64) function, public sll_f_pre_filter_int(mesh, local_index, deg)
Pre-filter PINT to compute the box splines coefficients.
real(kind=f64) function, public sll_f_pre_filter_piir1(mesh, local_index, deg)
Pre-filter PIIR1 to compute the box splines coefficients.
function, public sll_f_local_to_global(mesh, ref_index, local)
Transforms local index in a given reference local indexation to a global index from the mesh.
function, public sll_f_change_elements_notation(mesh, i_elmt_old)
Function that allows to change from the current element notation to one more intuitive.
integer(kind=i32) function, public sll_f_cells_to_origin(k1, k2)
Computes the number of cell from point to origin.
function, public sll_f_cart_to_hex2(mesh, x1, x2)
Transform cartesian coordinates to 2ndst hexagonal coordinates.
subroutine, public sll_s_write_caid_files(mesh, transf, spline_deg)
Writes files for CAID.
function, public sll_f_cart_to_hex1(mesh, x1, x2)
Transform cartesian coordinates to 1st hexagonal coordinates.
subroutine, public sll_s_get_cell_vertices_index(x, y, mesh, s1, s2, s3)
Returns indices of the edges of a given cell.
type(sll_t_hex_mesh_2d) function, pointer, public sll_f_new_hex_mesh_2d(num_cells, center_x1, center_x2, r11, r12, r21, r22, r31, r32, radius, EXTRA_TABLES)
Creates and initializes a new hexagonal mesh.
Some common numerical utilities.
Basic type for 2 dimensional box splines.
    Report Typos and Errors