Report Typos and Errors    
Semi-Lagrangian Library
Modular library for kinetic and gyrokinetic simulations of plasmas in fusion energy devices.
sll_m_bsplines.F90
Go to the documentation of this file.
1 
4 
6 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7 #include "sll_assert.h"
8 #include "sll_errors.h"
9 
10  use sll_m_working_precision, only: f64
14 
15  implicit none
16 
17  public :: &
22 
23  private
24 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
25 
27  integer, parameter :: wp = f64
28 
29 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
30 contains
31 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
32 
33  !-----------------------------------------------------------------------------
42  !-----------------------------------------------------------------------------
43  subroutine sll_s_bsplines_new( &
44  bsplines, &
45  degree, &
46  periodic, &
47  xmin, &
48  xmax, &
49  ncells, &
50  breaks)
51 
52  class(sll_c_bsplines), allocatable, intent(inout) :: bsplines
53  integer, intent(in) :: degree
54  logical, intent(in) :: periodic
55  real(wp), intent(in) :: xmin
56  real(wp), intent(in) :: xmax
57  integer, intent(in) :: ncells
58  real(wp), optional, intent(in) :: breaks(:)
59 
60  logical :: uniform
61 
62  ! Sanity checks
63  sll_assert(.not. allocated(bsplines))
64  sll_assert(degree > 0)
65  sll_assert(ncells > 0)
66  sll_assert(xmin < xmax)
67 
68  ! Determine if B-splines are uniform based on 'breaks' optional argument
69  uniform = .not. present(breaks)
70 
71  ! Non-uniform case: perform sanity checks on breakpoints
72  if (.not. uniform) then
73  sll_assert(size(breaks) == ncells + 1)
74  sll_assert(xmin == breaks(1))
75  sll_assert(xmax == breaks(size(breaks)))
76  end if
77 
78  ! Allocate B-splines object to correct type
79  if (uniform) then
80  allocate (sll_t_bsplines_uniform :: bsplines)
81  else
82  allocate (sll_t_bsplines_non_uniform :: bsplines)
83  end if
84 
85  ! Initialize B-splines object with type-specific constructor
86  select type (bsplines)
87  type is (sll_t_bsplines_uniform)
88  call bsplines%init(degree, periodic, xmin, xmax, ncells)
90  call bsplines%init(degree, periodic, breaks)
91  end select
92 
93  ! Set 'radial' flag to false
94  bsplines%radial = .false.
95 
96  end subroutine sll_s_bsplines_new
97 
98  !-----------------------------------------------------------------------------
100  !-----------------------------------------------------------------------------
102  bsplines_radial, &
103  bsplines_angular, &
104  degree, &
105  ncells, &
106  max_radius, &
107  theta_lims, &
108  breaks_radial, &
109  breaks_angular)
110 
111  class(sll_c_bsplines), allocatable, intent(inout) :: bsplines_radial
112  class(sll_c_bsplines), allocatable, intent(inout) :: bsplines_angular
113  integer, intent(in) :: degree(2)
114  integer, intent(in) :: ncells(2)
115  real(wp), intent(in) :: max_radius
116  real(wp), intent(in) :: theta_lims(2)
117  real(wp), optional, intent(in) :: breaks_radial(:)
118  real(wp), optional, intent(in) :: breaks_angular(:)
119 
120  character(len=*), parameter :: this_sub_name = "sll_s_bsplines_new_2d_polar"
121 
122  logical :: uniform(2)
123  real(wp) :: dr
124 
125  ! Sanity checks
126  sll_assert(.not. allocated(bsplines_radial))
127  sll_assert(.not. allocated(bsplines_angular))
128  sll_assert(degree(1) > 0)
129  sll_assert(degree(2) > 0)
130  sll_assert(ncells(1) > 0)
131  sll_assert(ncells(2) > 0)
132  sll_assert(theta_lims(1) < theta_lims(2))
133 
134  ! Specific checks for polar geometry
135  sll_assert(max_radius > 0.0_wp)
136  sll_assert(modulo(ncells(2), 2) == 0)
137 
138  ! We do not accept non-uniform splines yet
139  if (present(breaks_radial)) then
140  uniform(1) = .false.
141  sll_error(this_sub_name, "non-uniform option not yet implemented.")
142  else
143  uniform(1) = .true.
144  end if
145 
146  if (present(breaks_angular)) then
147  uniform(2) = .false.
148  sll_error(this_sub_name, "non-uniform option not yet implemented.")
149  else
150  uniform(2) = .true.
151  end if
152 
153  dr = max_radius/(real(ncells(1), wp) - 0.5_wp)
154 
155  call sll_s_bsplines_new( &
156  bsplines=bsplines_radial, &
157  degree=degree(1), &
158  periodic=.false., &
159  xmin=-0.5_wp*dr, &
160  xmax=max_radius, &
161  ncells=ncells(1), &
162  breaks=breaks_radial)
163 
164  call sll_s_bsplines_new( &
165  bsplines=bsplines_angular, &
166  degree=degree(2), &
167  periodic=.true., &
168  xmin=theta_lims(1), &
169  xmax=theta_lims(2), &
170  ncells=ncells(2), &
171  breaks=breaks_angular)
172 
173  ! Set 'radial' flag to true
174  bsplines_radial%radial = .true.
175 
176  end subroutine sll_s_bsplines_new_2d_polar
177 
178  !-----------------------------------------------------------------------------
180  !-----------------------------------------------------------------------------
181  subroutine sll_s_bsplines_new_mirror_copy(radial_basis, extended_basis)
182  class(sll_c_bsplines), intent(in) :: radial_basis
183  class(sll_c_bsplines), allocatable, intent(inout) :: extended_basis
184 
185  character(len=*), parameter :: this_sub_name = "sll_s_bsplines_new_mirror_copy"
186 
187  sll_assert(radial_basis%radial)
188  sll_assert(.not. allocated(extended_basis))
189 
190  select type (radial_basis)
191 
192  type is (sll_t_bsplines_uniform)
193  call sll_s_bsplines_new( &
194  bsplines=extended_basis, &
195  degree=radial_basis%degree, &
196  periodic=.false., &
197  xmin=-radial_basis%xmax, &
198  xmax=radial_basis%xmax, &
199  ncells=radial_basis%ncells*2 - 1)
200 
201  class default
202  sll_error(this_sub_name, "non-uniform option not yet implemented.")
203 
204  end select
205 
206  end subroutine sll_s_bsplines_new_mirror_copy
207 
208 end module sll_m_bsplines
Abstract class for B-splines of arbitrary degree.
Derived type for non-uniform B-splines of arbitrary degree.
Derived type for uniform B-splines of arbitrary degree.
Access point to B-splines of arbitrary degree providing factory function.
subroutine, public sll_s_bsplines_new_mirror_copy(radial_basis, extended_basis)
Create B-splines by mirroring radial basis onto extended domain [-R,R].
integer, parameter wp
Working precision.
subroutine, public sll_s_bsplines_new(bsplines, degree, periodic, xmin, xmax, ncells, breaks)
Allocate and initialize uniform or non-uniform B-splines.
subroutine, public sll_s_bsplines_new_2d_polar(bsplines_radial, bsplines_angular, degree, ncells, max_radius, theta_lims, breaks_radial, breaks_angular)
Allocate and initialize two B-splines for use on polar grid.
Module to select the kind parameter.
integer, parameter, public f64
f64 is the kind type for 64-bit reals (double precision)
    Report Typos and Errors