Report Typos and Errors    
Semi-Lagrangian Library
Modular library for kinetic and gyrokinetic simulations of plasmas in fusion energy devices.
sll_m_ellipt_2d_fem_sps_stencil_new_projector.F90
Go to the documentation of this file.
2 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 #include "sll_assert.h"
4 
6 
8 
10 
12 
13  implicit none
14 
16 
17  private
18 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
19 
20  ! Working precision
21  integer, parameter :: wp = f64
22 
24 
25  integer :: n1
26  integer :: n2
27  integer :: p1
28  integer :: p2
29 
30  ! Temporary storage needed for projection
31  real(wp), allocatable :: qp_temp(:, :, :)
32  real(wp), allocatable :: l(:, :, :)
33 
34  contains
35 
41 
43 
44 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
45 contains
46 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
47 
48  ! Initializer
49  subroutine s_ellipt_2d_fem_sps_stencil_new_projector__init(self, n1, n2, p1, p2, L)
50  class(sll_t_ellipt_2d_fem_sps_stencil_new_projector), intent(inout) :: self
51  integer, intent(in) :: n1
52  integer, intent(in) :: n2
53  integer, intent(in) :: p1
54  integer, intent(in) :: p2
55  real(wp), intent(in) :: L(:, :, :) ! matrix of barycentric coordinates
56 
57  self%n1 = n1
58  self%n2 = n2
59  self%p1 = p1
60  self%p2 = p2
61 
62  sll_assert(size(l, 1) == 2)
63  sll_assert(size(l, 2) == n2)
64  sll_assert(size(l, 3) == 3)
65 
66  ! Allocate temporary storage
67  allocate (self%L(size(l, 1), size(l, 2), size(l, 3)), source=l)
68  allocate (self%Qp_temp(size(l, 1), size(l, 2), size(l, 3)))
69 
71 
72  ! Change basis: C1 projection of stiffness and mass matrices
73  ! NOTE: 'self' has intent(inout) because temporary storage has to be assigned
75  class(sll_t_ellipt_2d_fem_sps_stencil_new_projector), intent(inout) :: self
76  type(sll_t_linear_operator_matrix_stencil_to_stencil), intent(inout) :: Ql
77  type(sll_t_linear_operator_matrix_c1_block_new), intent(inout) :: Qp
78 
79  integer :: i1, i2, j1, j2, k1, k2, ip, jp, ll
80 
81  associate(n1 => self%n1, &
82  n2 => self%n2, &
83  p1 => self%p1, &
84  p2 => self%p2)
85 
86  ! Fill blocks
87  self%Qp_temp(:, :, :) = 0.0_wp
88  qp%block1%A(:, :) = 0.0_wp
89  qp%block2%A(:, :, :) = 0.0_wp
90  qp%block3%A(:, :, :) = 0.0_wp
91  do ll = 1, 3
92  do i2 = 1, n2
93  do i1 = 1, n1
94  do k2 = -p2, p2
95  do k1 = -p1, p1
96 
97  j1 = i1 + k1
98  j2 = i2 + k2
99 
100  ! Hand-made modulo operation
101  if (j1 < 1) then
102  j1 = j1 + n1
103  else if (j1 > n1) then
104  j1 = j1 - n1
105  end if
106 
107  ! Hand-made modulo operation
108  if (j2 < 1) then
109  j2 = j2 + n2
110  else if (j2 > n2) then
111  j2 = j2 - n2
112  end if
113 
114  ! block 1: 3 x 3
115  if (i1 <= 2 .and. j1 <= 2) then
116  self%Qp_temp(i1, i2, ll) = self%Qp_temp(i1, i2, ll) + ql%A(k1, k2, i1, i2)*self%L(j1, j2, ll)
117  ! block 2: 3 x (n1-2)*n2
118  else if (i1 <= 2 .and. j1 <= 2 + p1) then
119  qp%block2%A(ll, j1 - 2, j2) = qp%block2%A(ll, j1 - 2, j2) + self%L(i1, i2, ll)*ql%A(k1, k2, i1, i2)
120  ! block 3: (n1-2)*n2 x 3
121  else if (i1 <= 2 + p1 .and. j1 <= 2) then
122  qp%block3%A(i1 - 2, i2, ll) = qp%block3%A(i1 - 2, i2, ll) + ql%A(k1, k2, i1, i2)*self%L(j1, j2, ll)
123  end if
124 
125  end do
126  end do
127  end do
128  end do
129  end do
130  ! complete calculation of block 1
131  do ip = 1, 3
132  do jp = 1, 3
133  do i2 = 1, n2
134  do i1 = 1, 2
135  qp%block1%A(ip, jp) = qp%block1%A(ip, jp) + self%L(i1, i2, ip)*self%Qp_temp(i1, i2, jp)
136  end do
137  end do
138  end do
139  end do
140 
141  ! block 4: (n1-2)*n2 x (n1-2)*n2
142  qp%block4%A(:, :, :, :) = 0.0_wp
143  do i2 = 1, n2
144  do i1 = 1, n1 - 2
145  do k2 = -p2, p2
146  do k1 = -p1, p1
147  j1 = modulo(i1 - 1 + k1, n1 - 2)
148  ll = modulo(i1 + 1 + k1, n1)
149  if (ll == 2 + j1) qp%block4%A(k1, k2, i1, i2) = ql%A(k1, k2, i1 + 2, i2)
150  end do
151  end do
152  end do
153  end do
154 
155  end associate
156 
158 
159  ! Change basis: C1 projection of vectors
161  class(sll_t_ellipt_2d_fem_sps_stencil_new_projector), intent(in) :: self
162  real(wp), intent(in) :: V(:, :)
163  type(sll_t_vector_space_c1_block), intent(inout) :: Vp
164 
165  integer :: i1, i2, ll
166 
167  associate(n1 => self%n1, &
168  n2 => self%n2, &
169  p1 => self%p1, &
170  p2 => self%p2)
171 
172  ! Checks
173  sll_assert(size(v, 1) == n1)
174  sll_assert(size(v, 2) == n2)
175  sll_assert(size(vp%vd%array) == 3)
176  sll_assert(size(vp%vs%array, 1) == n1 - 2 + 2*p1)
177  sll_assert(size(vp%vs%array, 2) == n2 + 2*p2)
178 
179  vp%vd%array(:) = 0.0_wp
180  do ll = 1, 3
181  do i2 = 1, n2
182  do i1 = 1, 2
183  vp%vd%array(ll) = vp%vd%array(ll) + self%L(i1, i2, ll)*v(i1, i2)
184  end do
185  end do
186  end do
187 
188  do i2 = 1, n2
189  do i1 = 3, n1
190  vp%vs%array(i1 - 2, i2) = v(i1, i2)
191  end do
192  end do
193 
194  end associate
195 
197 
198  ! Change basis: C1 projection of vectors
200  class(sll_t_ellipt_2d_fem_sps_stencil_new_projector), intent(in) :: self
201  type(sll_t_vector_space_c1_block), intent(inout) :: Vp
202  real(wp), intent(inout) :: V(:)
203 
204  integer :: i, i1, i2, j, j1, j2, ll
205 
206  associate(n1 => self%n1, &
207  n2 => self%n2, &
208  p1 => self%p1, &
209  p2 => self%p2)
210 
211  ! Checks
212  sll_assert(size(vp%vd%array) == 3)
213  sll_assert(size(vp%vs%array, 1) == n1 - 2 + 2*p1)
214  sll_assert(size(vp%vs%array, 2) == n2 + 2*p2)
215  sll_assert(size(v) == n1*n2)
216 
217  v(:) = 0.0_wp
218  do ll = 1, 3
219  do i2 = 1, n2
220  do i1 = 1, 2
221  i = (i1 - 1)*n2 + i2
222  v(i) = v(i) + self%L(i1, i2, ll)*vp%vd%array(ll)
223  end do
224  end do
225  end do
226 
227  do j2 = 1, n2
228  do j1 = 1, n1 - 2
229  j = (j1 - 1)*n2 + j2
230  v(2*n2 + j) = vp%vs%array(j1, j2)
231  end do
232  end do
233 
234  end associate
235 
237 
238  ! Deallocate allocatables
240  class(sll_t_ellipt_2d_fem_sps_stencil_new_projector), intent(inout) :: self
241 
242  deallocate (self%Qp_temp)
243  deallocate (self%L)
244 
246 
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)
    Report Typos and Errors