Report Typos and Errors    
Semi-Lagrangian Library
Modular library for kinetic and gyrokinetic simulations of plasmas in fusion energy devices.
sll_m_linear_operator_matrix_stencil_to_stencil.F90
Go to the documentation of this file.
2 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 #include "sll_assert.h"
4 #include "sll_errors.h"
5 
7 
9 
11 
13 
14  implicit none
15 
17 
18  private
19 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
20 
21  ! Working precision
22  integer, parameter :: wp = f64
23 
25 
26  real(wp), allocatable :: a(:, :, :, :)
27 
28  integer :: s1
29  integer :: s2
30  integer :: p1
31  integer :: p2
32 
33  contains
34 
41 
43 
44 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
45 contains
46 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
47 
48  ! Initialize linear operator
49  subroutine s_linear_operator_matrix_stencil_to_stencil__init(self, s1, s2, p1, p2)
50  class(sll_t_linear_operator_matrix_stencil_to_stencil), intent(inout) :: self
51  integer, intent(in) :: s1
52  integer, intent(in) :: s2
53  integer, intent(in) :: p1
54  integer, intent(in) :: p2
55 
56  allocate (self%A(-p1:p1, -p2:p2, 1:s1, 1:s2))
57 
58  self%s1 = s1
59  self%s2 = s2
60  self%p1 = p1
61  self%p2 = p2
62 
64 
65  ! Get shape of linear operator
67  class(sll_t_linear_operator_matrix_stencil_to_stencil), intent(in) :: self
68  integer :: s(2)
69 
70  s(1) = size(self%A, 3)*size(self%A, 4)
71  s(2) = s(1)
72 
74 
75  ! Implement y=Ax, with A stencil matrix (4D), x and y stencil vectors (2D)
77  class(sll_t_linear_operator_matrix_stencil_to_stencil), intent(in) :: self
78  class(sll_c_vector_space), intent(in) :: x ! stencil
79  class(sll_c_vector_space), intent(inout) :: y ! stencil
80 
81  integer :: i1, i2, j1, j2, k1, k2
82  real(wp) :: temp
83 
84  character(len=*), parameter :: this_sub_name = "sll_t_linear_operator_matrix_stencil_to_stencil % dot"
85  character(len=64) :: err_msg
86 
87  associate(s1 => self%s1, &
88  s2 => self%s2, &
89  p1 => self%p1, &
90  p2 => self%p2)
91 
92  select type (x)
93 
95 
96  ! Check dimensions
97  sll_assert(self%p1 == -lbound(x%array, 1) + 1)
98  sll_assert(self%p2 == -lbound(x%array, 2) + 1)
99  sll_assert(self%s1 == ubound(x%array, 1) + lbound(x%array, 1) - 1)
100  sll_assert(self%s2 == ubound(x%array, 2) + lbound(x%array, 2) - 1)
101 
102  select type (y)
103 
105 
106  ! Check dimensions
107  sll_assert(self%p1 == -lbound(y%array, 1) + 1)
108  sll_assert(self%p2 == -lbound(y%array, 2) + 1)
109  sll_assert(self%s1 == ubound(y%array, 1) + lbound(y%array, 1) - 1)
110  sll_assert(self%s2 == ubound(y%array, 2) + lbound(y%array, 2) - 1)
111 
112  y%array = 0.0_wp
113 
114 !$OMP PARALLEL DO PRIVATE(j1,j2,temp)
115  do i2 = 1, s2
116  do i1 = 1, s1
117 
118  temp = 0.0_wp
119 
120  do k2 = -p2, p2
121  do k1 = -p1, p1
122 
123  j1 = i1 + k1
124  j2 = i2 + k2
125 
126  ! Hand-made modulo operation
127  if (j1 < 1) then
128  j1 = j1 + s1
129  else if (j1 > s1) then
130  j1 = j1 - s1
131  end if
132 
133  ! Hand-made modulo operation
134  if (j2 < 1) then
135  j2 = j2 + s2
136  else if (j2 > s2) then
137  j2 = j2 - s2
138  end if
139 
140  temp = temp + self%A(k1, k2, i1, i2)*x%array(j1, j2)
141 
142  end do
143  end do
144 
145  y%array(i1, i2) = y%array(i1, i2) + temp
146 
147  end do
148  end do
149 !$OMP END PARALLEL DO
150 
151  ! Update buffer regions
152  y%array(1 - p1:0, :) = y%array(s1 - p1 + 1:s1, :)
153  y%array(s1 + 1:s1 + p1, :) = y%array(1:p1, :)
154  y%array(:, 1 - p2:0) = y%array(:, s2 - p2 + 1:s2)
155  y%array(:, s2 + 1:s2 + p2) = y%array(:, 1:p2)
156 
157  class default
158  err_msg = "y must be of type sll_t_vector_space_real_array_2d"
159  sll_error(this_sub_name, err_msg)
160 
161  end select
162 
163  class default
164  err_msg = "x must be of type sll_t_vector_space_real_array_2d"
165  sll_error(this_sub_name, err_msg)
166 
167  end select
168 
169  end associate
170 
172 
173  ! Implement y=y+Ax, with A stencil matrix (4D), x and y stencil vectors (2D)
175  class(sll_t_linear_operator_matrix_stencil_to_stencil), intent(in) :: self
176  class(sll_c_vector_space), intent(in) :: x ! stencil
177  class(sll_c_vector_space), intent(inout) :: y ! stencil
178 
179  integer :: i1, i2, j1, j2, k1, k2
180  real(wp) :: temp
181 
182  character(len=*), parameter :: this_sub_name = "sll_t_linear_operator_matrix_stencil_to_stencil % dot"
183  character(len=64) :: err_msg
184 
185  associate(s1 => self%s1, &
186  s2 => self%s2, &
187  p1 => self%p1, &
188  p2 => self%p2)
189 
190  select type (x)
191 
192  type is (sll_t_vector_space_real_array_2d)
193 
194  ! Check dimensions
195  sll_assert(self%p1 == -lbound(x%array, 1) + 1)
196  sll_assert(self%p2 == -lbound(x%array, 2) + 1)
197  sll_assert(self%s1 == ubound(x%array, 1) + lbound(x%array, 1) - 1)
198  sll_assert(self%s2 == ubound(x%array, 2) + lbound(x%array, 2) - 1)
199 
200  select type (y)
201 
202  type is (sll_t_vector_space_real_array_2d)
203 
204  ! Check dimensions
205  sll_assert(self%p1 == -lbound(y%array, 1) + 1)
206  sll_assert(self%p2 == -lbound(y%array, 2) + 1)
207  sll_assert(self%s1 == ubound(y%array, 1) + lbound(y%array, 1) - 1)
208  sll_assert(self%s2 == ubound(y%array, 2) + lbound(y%array, 2) - 1)
209 
210 !$OMP PARALLEL DO PRIVATE(j1,j2,temp)
211  do i2 = 1, s2
212  do i1 = 1, s1
213 
214  temp = 0.0_wp
215 
216  do k2 = -p2, p2
217  do k1 = -p1, p1
218 
219  j1 = i1 + k1
220  j2 = i2 + k2
221 
222  ! Hand-made modulo operation
223  if (j1 < 1) then
224  j1 = j1 + s1
225  else if (j1 > s1) then
226  j1 = j1 - s1
227  end if
228 
229  ! Hand-made modulo operation
230  if (j2 < 1) then
231  j2 = j2 + s2
232  else if (j2 > s2) then
233  j2 = j2 - s2
234  end if
235 
236  temp = temp + self%A(k1, k2, i1, i2)*x%array(j1, j2)
237 
238  end do
239  end do
240 
241  y%array(i1, i2) = y%array(i1, i2) + temp
242 
243  end do
244  end do
245 !$OMP END PARALLEL DO
246 
247  ! Update buffer regions
248  y%array(1 - p1:0, :) = y%array(s1 - p1 + 1:s1, :)
249  y%array(s1 + 1:s1 + p1, :) = y%array(1:p1, :)
250  y%array(:, 1 - p2:0) = y%array(:, s2 - p2 + 1:s2)
251  y%array(:, s2 + 1:s2 + p2) = y%array(:, 1:p2)
252 
253  class default
254  err_msg = "y must be of type sll_t_vector_space_real_array_2d"
255  sll_error(this_sub_name, err_msg)
256 
257  end select
258 
259  class default
260  err_msg = "x must be of type sll_t_vector_space_real_array_2d"
261  sll_error(this_sub_name, err_msg)
262 
263  end select
264 
265  end associate
266 
268 
269  ! Convert stencil matrix to dense matrix
271  class(sll_t_linear_operator_matrix_stencil_to_stencil), intent(in) :: self
272  real(wp), intent(inout) :: A(:, :)
273 
274  integer :: i, j, i1, i2, j1, j2, k1, k2
275 
276  associate(s1 => self%s1, &
277  s2 => self%s2, &
278  p1 => self%p1, &
279  p2 => self%p2)
280 
281  sll_assert(size(a, 1) == s1*s2)
282  sll_assert(size(a, 2) == s1*s2)
283 
284  do i2 = 1, s2
285  do i1 = 1, s1
286  do k2 = -p2, p2
287  do k1 = -p1, p1
288  j1 = modulo(i1 - 1 + k1, s1) + 1
289  j2 = modulo(i2 - 1 + k2, s2) + 1
290  i = (i1 - 1)*s2 + i2
291  j = (j1 - 1)*s2 + j2
292  a(i, j) = self%A(k1, k2, i1, i2)
293  end do
294  end do
295  end do
296  end do
297 
298  end associate
299 
301 
302  ! Free objects
304  class(sll_t_linear_operator_matrix_stencil_to_stencil), intent(inout) :: self
305 
306  deallocate (self%A)
307 
309 
Abstract type implementing a generic vector space.
Vector space for wrapping 2D Fortran real arrays.
Module to select the kind parameter.
integer, parameter, public f64
f64 is the kind type for 64-bit reals (double precision)
Abstract base class for all vector spaces.
    Report Typos and Errors