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_c1_block_new.F90
Go to the documentation of this file.
2 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 #include "sll_assert.h"
4 #include "sll_errors.h"
5 
7 
9 
11 
13 
15 
17 
19 
21 
22  implicit none
23 
25 
26  private
27 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
28 
29  ! Working precision
30  integer, parameter :: wp = f64
31 
33 
34  integer :: n1
35  integer :: n2
36  integer :: p1
37  integer :: p2
38 
43 
44  contains
45 
52 
54 
55 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
56 contains
57 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
58 
59  ! Initialize linear operator
60  subroutine s_linear_operator_matrix_c1_block_new__init(self, n1, n2, p1, p2)
61  class(sll_t_linear_operator_matrix_c1_block_new), intent(inout) :: self
62  integer, intent(in) :: n1
63  integer, intent(in) :: n2
64  integer, intent(in) :: p1
65  integer, intent(in) :: p2
66 
67  self%n1 = n1
68  self%n2 = n2
69  self%p1 = p1
70  self%p2 = p2
71 
72  call self%block1%init(3, 3)
73  call self%block2%init(3, p1, n2)
74  call self%block3%init(p1, n2, 3)
75  call self%block4%init(n1 - 2, n2, p1, p2)
76 
78 
79  ! Get shape of linear operator
81  class(sll_t_linear_operator_matrix_c1_block_new), intent(in) :: self
82  integer :: s(2)
83 
84  s = self%block1%get_shape() + self%block2%get_shape() + &
85  self%block3%get_shape() + self%block4%get_shape()
86 
88 
89  ! Implement y=Ax, with A C1 block matrix, x and y C1 block vectors
91  class(sll_t_linear_operator_matrix_c1_block_new), intent(in) :: self
92  class(sll_c_vector_space), intent(in) :: x
93  class(sll_c_vector_space), intent(inout) :: y
94 
95  character(len=*), parameter :: this_sub_name = "sll_t_linear_operator_matrix_c1_block % dot"
96  character(len=64) :: err_msg
97 
98  select type (x)
99 
101 
102  select type (y)
103 
105 
106  call self%block1%dot(x%vd, y%vd)
107  call self%block2%dot_incr(x%vs, y%vd)
108  call self%block3%dot(x%vd, y%vs)
109  call self%block4%dot_incr(x%vs, y%vs)
110 
111  class default
112  err_msg = "y must be of type sll_t_vector_space_c1_block"
113  sll_error(this_sub_name, err_msg)
114 
115  end select
116 
117  class default
118  err_msg = "x must be of type sll_t_vector_space_c1_block"
119  sll_error(this_sub_name, err_msg)
120 
121  end select
122 
124 
125  ! Implement y=y+Ax, with A C1 block matrix, x and y C1 block vectors
127  class(sll_t_linear_operator_matrix_c1_block_new), intent(in) :: self
128  class(sll_c_vector_space), intent(in) :: x
129  class(sll_c_vector_space), intent(inout) :: y
130 
131  character(len=*), parameter :: this_sub_name = "sll_t_linear_operator_matrix_c1_block_new_new % dot_incr"
132  character(len=64) :: err_msg
133 
134  select type (x)
135 
137 
138  select type (y)
139 
141 
142  call self%block1%dot_incr(x%vd, y%vd)
143  call self%block2%dot_incr(x%vs, y%vd)
144  call self%block3%dot_incr(x%vd, y%vs)
145  call self%block4%dot_incr(x%vs, y%vs)
146 
147  class default
148  err_msg = "y must be of type sll_t_vector_space_c1_block"
149  sll_error(this_sub_name, err_msg)
150 
151  end select
152 
153  class default
154  err_msg = "x must be of type sll_t_vector_space_c1_block"
155  sll_error(this_sub_name, err_msg)
156 
157  end select
158 
160 
161  ! Convert C1 block matrix to dense matrix
163  class(sll_t_linear_operator_matrix_c1_block_new), intent(in) :: self
164  real(wp), intent(inout) :: A(:, :)
165 
166  integer :: i, j, i1, i2, j1, j2, k1, k2
167 
168  ! Indices 1,2,3 correspond to dense blocks
169  sll_assert(size(a, 1) == 3 + (self%n1 - 2)*self%n2)
170  sll_assert(size(a, 2) == 3 + (self%n1 - 2)*self%n2)
171 
172  associate(n1 => self%n1, &
173  n2 => self%n2, &
174  p1 => self%p1, &
175  p2 => self%p2)
176 
177  ! block 1
178  a(1:3, 1:3) = self%block1%A(:, :)
179 
180  ! block 2
181  do i2 = 1, n2
182  do i1 = 1, p1
183  i = (i1 - 1)*n2 + i2
184  a(1:3, i + 3) = self%block2%A(:, i1, i2)
185  end do
186  end do
187  a(1:3, 4 + p1:3 + (n1 - 2)*n2) = 0.0_wp
188 
189  ! block 3
190  do i2 = 1, n2
191  do i1 = 1, p1
192  i = (i1 - 1)*n2 + i2
193  a(i + 3, 1:3) = self%block3%A(i1, i2, :)
194  end do
195  end do
196  a(4 + p1:3 + (n1 - 2)*n2, 1:3) = 0.0_wp
197 
198  ! block 4
199  do i2 = 1, n2
200  do i1 = 1, n1 - 2
201  do k2 = -p2, p2
202  do k1 = -p1, p1
203  j1 = modulo(i1 - 1 + k1, n1 - 2) + 1
204  j2 = modulo(i2 - 1 + k2, n2) + 1
205  i = (i1 - 1)*n2 + i2
206  j = (j1 - 1)*n2 + j2
207  a(i + 3, j + 3) = self%block4%A(k1, k2, i1, i2)
208  end do
209  end do
210  end do
211  end do
212 
213  end associate
214 
216 
217  ! Free objects
219  class(sll_t_linear_operator_matrix_c1_block_new), intent(inout) :: self
220 
221  call self%block1%free()
222  call self%block2%free()
223  call self%block3%free()
224  call self%block4%free()
225 
227 
integer function, dimension(2) f_linear_operator_matrix_c1_block_new__get_shape(self)
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