Report Typos and Errors    
Semi-Lagrangian Library
Modular library for kinetic and gyrokinetic simulations of plasmas in fusion energy devices.
sll_m_poisson_2d_periodic.F90
Go to the documentation of this file.
1 !**************************************************************
2 ! Copyright INRIA
3 ! Authors :
4 ! CALVI project team
5 !
6 ! This code SeLaLib (for Semi-Lagrangian-Library)
7 ! is a parallel library for simulating the plasma turbulence
8 ! in a tokamak.
9 !
10 ! This software is governed by the CeCILL-B license
11 ! under French law and abiding by the rules of distribution
12 ! of free software. You can use, modify and redistribute
13 ! the software under the terms of the CeCILL-B license as
14 ! circulated by CEA, CNRS and INRIA at the following URL
15 ! "http://www.cecill.info".
16 !**************************************************************
17 
26 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
27 #include "sll_memory.h"
28 #include "sll_working_precision.h"
29 #include "sll_assert.h"
30 
31  use sll_m_poisson_2d_base, only: &
34 
35  use sll_m_constants, only: &
36  sll_p_pi
37  use sll_m_fft, only: sll_t_fft, &
43  implicit none
44 
45  private
46 
50 
54 
55  private
56  sll_real64, dimension(:, :), pointer :: kx
57  sll_real64, dimension(:, :), pointer :: ky
58  sll_real64, dimension(:, :), pointer :: k2
59  sll_int32 :: nc_x
60  sll_int32 :: nc_y
61  sll_real64 :: dx
62  sll_real64 :: dy
63  sll_comp64, pointer :: rht(:, :)
64  sll_comp64, pointer :: exy(:, :)
65  type(sll_t_fft) :: fw
66  type(sll_t_fft) :: bw
67  type(sll_t_fft) :: p_rho
68  type(sll_t_fft) :: p_exy
69  type(sll_t_fft) :: p_tmp
70  sll_real64, pointer :: tmp(:, :)
71 
73 
74  interface sll_o_initialize
75  module procedure initialize_poisson_2d_periodic_fft
76  end interface
77 
78  interface sll_o_solve
81  end interface
82 
84 
85  type(sll_t_poisson_2d_periodic_fft), private :: solver
86 
87  contains
88 
90  procedure, public, pass(poisson) :: init => &
93  procedure, public, pass(poisson) :: compute_phi_from_rho => &
96  procedure, public, pass(poisson) :: compute_e_from_rho => &
98 
100  procedure :: &
101  l2norm_squared => l2norm_squarred_2d_periodic
103  procedure :: &
104  compute_rhs_from_function => compute_rhs_from_function_2d_periodic
106  procedure :: free => delete_2d_periodic
107 
109 
110 contains
111 
112  function l2norm_squarred_2d_periodic(poisson, coefs_dofs) result(r)
113  class(sll_t_poisson_2d_periodic), intent(in) :: poisson
114  sll_real64, intent(in) :: coefs_dofs(:, :)
115  sll_real64 :: r
116 
117  r = sum(coefs_dofs**2)*poisson%solver%dx*poisson%solver%dy
118 
119  end function l2norm_squarred_2d_periodic
120 
121  subroutine compute_rhs_from_function_2d_periodic(poisson, func, coefs_dofs)
122  class(sll_t_poisson_2d_periodic) :: poisson
123  procedure(sll_i_function_of_position) :: func
124  sll_real64, intent(out) :: coefs_dofs(:)
125 
126  print *, 'compute_rhs_from_function not implemented for sll_t_poisson_2d_periodic.'
127 
129 
130  subroutine delete_2d_periodic(poisson)
131  class(sll_t_poisson_2d_periodic) :: poisson
132  end subroutine delete_2d_periodic
133 
136  eta1_min, &
137  eta1_max, &
138  nc_eta1, &
139  eta2_min, &
140  eta2_max, &
141  nc_eta2) &
142  result(poisson)
143 
144  type(sll_t_poisson_2d_periodic), pointer :: poisson
145  sll_real64 :: eta1_min
146  sll_real64 :: eta1_max
147  sll_int32 :: nc_eta1
148  sll_real64 :: eta2_min
149  sll_real64 :: eta2_max
150  sll_int32 :: nc_eta2
151  sll_int32 :: ierr
152 
153  sll_allocate(poisson, ierr)
155  poisson, &
156  eta1_min, &
157  eta1_max, &
158  nc_eta1, &
159  eta2_min, &
160  eta2_max, &
161  nc_eta2)
162 
163  end function sll_f_new_poisson_2d_periodic
164 
166  poisson, &
167  eta1_min, &
168  eta1_max, &
169  nc_eta1, &
170  eta2_min, &
171  eta2_max, &
172  nc_eta2)
173  class(sll_t_poisson_2d_periodic) :: poisson
174  sll_real64 :: eta1_min
175  sll_real64 :: eta1_max
176  sll_int32 :: nc_eta1
177  sll_real64 :: eta2_min
178  sll_real64 :: eta2_max
179  sll_int32 :: nc_eta2
180  sll_int32 :: ierr
181 
182  call sll_o_initialize( &
183  poisson%solver, &
184  eta1_min, &
185  eta1_max, &
186  nc_eta1, &
187  eta2_min, &
188  eta2_max, &
189  nc_eta2, &
190  ierr)
191 
192  end subroutine initialize_poisson_2d_periodic
193 
195  subroutine compute_phi_from_rho_2d_fft(poisson, phi, rho)
196  class(sll_t_poisson_2d_periodic) :: poisson
197  sll_real64, dimension(:, :), intent(in) :: rho
198  sll_real64, dimension(:, :), intent(out) :: phi
199 
200  call sll_o_solve(poisson%solver, phi, rho)
201 
202  end subroutine compute_phi_from_rho_2d_fft
203 
212  subroutine compute_e_from_rho_2d_fft(poisson, E1, E2, rho)
213  class(sll_t_poisson_2d_periodic) :: poisson
214  sll_real64, dimension(:, :), intent(in) :: rho
215  sll_real64, dimension(:, :), intent(out) :: e1
216  sll_real64, dimension(:, :), intent(out) :: e2
217 
218  call sll_o_solve(poisson%solver, e1, e2, rho)
219 
220  end subroutine compute_e_from_rho_2d_fft
221 
225  x_min, &
226  x_max, &
227  nc_x, &
228  y_min, &
229  y_max, &
230  nc_y, &
231  error) &
232  result(self)
233 
234  type(sll_t_poisson_2d_periodic_fft), pointer :: self
235  sll_int32, intent(in) :: nc_x
236  sll_int32, intent(in) :: nc_y
237  sll_real64, intent(in) :: x_min
238  sll_real64, intent(in) :: x_max
239  sll_real64, intent(in) :: y_min
240  sll_real64, intent(in) :: y_max
241  sll_int32, intent(out) :: error
242 
243  sll_allocate(self, error)
245  self, x_min, x_max, nc_x, y_min, y_max, nc_y, error)
246 
247  end function new_poisson_2d_periodic_fft
248 
251  x_min, &
252  x_max, &
253  nc_x, &
254  y_min, &
255  y_max, &
256  nc_y, &
257  error)
258 
259  type(sll_t_poisson_2d_periodic_fft) :: self
260  sll_real64, intent(in) :: x_min
261  sll_real64, intent(in) :: x_max
262  sll_real64, intent(in) :: y_min
263  sll_real64, intent(in) :: y_max
264  sll_int32 :: error
265  sll_int32 :: nc_x
266  sll_int32 :: nc_y
267  sll_int32 :: ik, jk
268  sll_real64 :: kx1, kx0, ky0
269 
270  self%nc_x = nc_x
271  self%nc_y = nc_y
272 
273  self%dx = (x_max - x_min)/real(nc_x, f64)
274  self%dy = (y_max - y_min)/real(nc_y, f64)
275 
276 #ifdef DEBUG
277  print *, " FFT version of poisson 2d periodic solver "
278 #endif
279 
280  sll_allocate(self%rht(1:nc_x/2 + 1, 1:nc_y), error)
281  sll_allocate(self%exy(1:nc_x/2 + 1, 1:nc_y), error)
282  sll_clear_allocate(self%tmp(1:nc_x, 1:nc_y), error)
283  call sll_s_fft_init_r2c_2d(self%fw, nc_x, nc_y, self%tmp, self%rht)
284  call sll_s_fft_init_c2r_2d(self%bw, nc_x, nc_y, self%rht, self%tmp)
285 
286  sll_allocate(self%kx(nc_x/2 + 1, nc_y), error)
287  sll_allocate(self%ky(nc_x/2 + 1, nc_y), error)
288  sll_allocate(self%k2(nc_x/2 + 1, nc_y), error)
289 
290  kx0 = 2._f64*sll_p_pi/(x_max - x_min)
291  ky0 = 2._f64*sll_p_pi/(y_max - y_min)
292 
293  do ik = 1, nc_x/2 + 1
294  kx1 = (ik - 1)*kx0
295  do jk = 1, nc_y/2
296  self%kx(ik, jk) = kx1
297  self%ky(ik, jk) = (jk - 1)*ky0
298  end do
299  do jk = nc_y/2 + 1, nc_y
300  self%kx(ik, jk) = kx1
301  self%ky(ik, jk) = (jk - 1 - nc_y)*ky0
302  end do
303  end do
304 
305  self%kx(1, 1) = 1.0_f64
306  self%k2 = self%kx*self%kx + self%ky*self%ky
307  self%kx = self%kx/self%k2
308  self%ky = self%ky/self%k2
309 
311 
314  subroutine solve_potential_poisson_2d_periodic_fft(self, phi, rho)
315 
316  type(sll_t_poisson_2d_periodic_fft) :: self
317  sll_real64, dimension(:, :), intent(in) :: rho
318  sll_real64, dimension(:, :), intent(out) :: phi
319  sll_int32 :: nc_x
320  sll_int32 :: nc_y
321 
322  nc_x = self%nc_x
323  nc_y = self%nc_y
324 
325  self%tmp = rho(1:nc_x, 1:nc_y)
326  call sll_s_fft_exec_r2c_2d(self%fw, self%tmp, self%rht)
327 
328  self%rht = self%rht/self%k2
329 
330  call sll_s_fft_exec_c2r_2d(self%bw, self%rht, self%tmp)
331 
332  phi(1:nc_x, 1:nc_y) = self%tmp/real(nc_x*nc_y, f64)
333 
334  !Node centered case
335  if (size(phi, 1) == nc_x + 1) phi(nc_x + 1, :) = phi(1, :)
336  if (size(phi, 2) == nc_y + 1) phi(:, nc_y + 1) = phi(:, 1)
337 
339 
342  subroutine solve_e_fields_poisson_2d_periodic_fft(self, e_x, e_y, rho, nrj)
343 
344  type(sll_t_poisson_2d_periodic_fft), intent(inout) :: self
345  sll_real64, dimension(:, :), intent(in) :: rho
346  sll_real64, dimension(:, :), intent(out) :: e_x
347  sll_real64, dimension(:, :), intent(out) :: e_y
348  sll_real64, optional :: nrj
349 
350  sll_int32 :: nc_x, nc_y
351  sll_real64 :: dx, dy
352 
353  nc_x = self%nc_x
354  nc_y = self%nc_y
355 
356  self%tmp = rho(1:nc_x, 1:nc_y)
357  call sll_s_fft_exec_r2c_2d(self%fw, self%tmp, self%rht)
358 
359  self%exy(1, 1) = (0.0_f64, 0.0_f64)
360  self%exy = -cmplx(0.0_f64, self%kx, kind=f64)*self%rht
361  call sll_s_fft_exec_c2r_2d(self%bw, self%exy, self%tmp)
362  e_x(1:nc_x, 1:nc_y) = self%tmp/real(nc_x*nc_y, f64)
363 
364  self%exy(1, 1) = (0.0_f64, 0.0_f64)
365  self%exy = -cmplx(0.0_f64, self%ky, kind=f64)*self%rht
366  call sll_s_fft_exec_c2r_2d(self%bw, self%exy, self%tmp)
367 
368  e_y(1:nc_x, 1:nc_y) = self%tmp/real(nc_x*nc_y, f64)
369 
370  !Node centered case
371  if (size(e_x, 1) == nc_x + 1) e_x(nc_x + 1, :) = e_x(1, :)
372  if (size(e_x, 2) == nc_y + 1) e_x(:, nc_y + 1) = e_x(:, 1)
373  if (size(e_y, 1) == nc_x + 1) e_y(nc_x + 1, :) = e_y(1, :)
374  if (size(e_y, 2) == nc_y + 1) e_y(:, nc_y + 1) = e_y(:, 1)
375 
376  if (present(nrj)) then
377  dx = self%dx
378  dy = self%dy
379  nrj = sum(e_x(1:nc_x, 1:nc_y)*e_x(1:nc_x, 1:nc_y) &
380  + e_y(1:nc_x, 1:nc_y)*e_y(1:nc_x, 1:nc_y))*dx*dy
381  end if
382 
384 
387 
388  type(sll_t_poisson_2d_periodic_fft) :: self
389 
390  call sll_s_fft_free(self%fw)
391  call sll_s_fft_free(self%bw)
392 
393  end subroutine delete_poisson_2d_periodic_fft
394 
395 end module sll_m_poisson_2d_periodic
Fortran module where set some physical and mathematical constants.
real(kind=f64), parameter, public sll_p_pi
FFT interface for FFTW.
subroutine, public sll_s_fft_free(plan)
Delete a plan.
subroutine, public sll_s_fft_exec_c2r_2d(plan, array_in, array_out)
Compute fast Fourier transform in complex to real mode.
subroutine, public sll_s_fft_init_c2r_2d(plan, nx, ny, array_in, array_out, normalized, aligned, optimization)
Create new 2d real to complex plan for backward FFT.
subroutine, public sll_s_fft_exec_r2c_2d(plan, array_in, array_out)
Compute fast Fourier transform in real to complex mode.
subroutine, public sll_s_fft_init_r2c_2d(plan, nx, ny, array_in, array_out, normalized, aligned, optimization)
Create new 2d complex to real plan for forward FFT.
Module interface to solve Poisson equation in 2D.
Regular cartesian two dimensional mesh with periodic bounday conditions.
type(sll_t_poisson_2d_periodic) function, pointer, public sll_f_new_poisson_2d_periodic(eta1_min, eta1_max, nc_eta1, eta2_min, eta2_max, nc_eta2)
subroutine initialize_poisson_2d_periodic_fft(self, x_min, x_max, nc_x, y_min, y_max, nc_y, error)
sll_o_initialize the Poisson solver
real(kind=f64) function l2norm_squarred_2d_periodic(poisson, coefs_dofs)
subroutine solve_e_fields_poisson_2d_periodic_fft(self, e_x, e_y, rho, nrj)
sll_o_solve Poisson equation on 2D mesh with periodic boundary conditions. return electric fields.
type(sll_t_poisson_2d_periodic_fft) function, pointer new_poisson_2d_periodic_fft(x_min, x_max, nc_x, y_min, y_max, nc_y, error)
Create a sll_o_new solver.
subroutine delete_poisson_2d_periodic_fft(self)
Delete the Poisson object.
subroutine compute_rhs_from_function_2d_periodic(poisson, func, coefs_dofs)
subroutine compute_phi_from_rho_2d_fft(poisson, phi, rho)
solves
subroutine initialize_poisson_2d_periodic(poisson, eta1_min, eta1_max, nc_eta1, eta2_min, eta2_max, nc_eta2)
subroutine solve_potential_poisson_2d_periodic_fft(self, phi, rho)
sll_o_solve Poisson equation on 2D mesh with periodic boundary conditions. return potential.
subroutine compute_e_from_rho_2d_fft(poisson, E1, E2, rho)
sll_o_solve Poisson equation to compute electric fields
Type for FFT plan in SeLaLib.
derived type to sll_o_solve the Poisson equation on 2d regular cartesian mesh with periodic boundary ...
    Report Typos and Errors