Report Typos and Errors    
Semi-Lagrangian Library
Modular library for kinetic and gyrokinetic simulations of plasmas in fusion energy devices.
sll_m_maxwell_clamped_3d_trafo_parallel.F90
Go to the documentation of this file.
1 
8 
10  !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11 #include "sll_assert.h"
12 #include "sll_memory.h"
13 #include "sll_working_precision.h"
14 
15 
16  use sll_m_collective, only: &
22 
23  use sll_m_mapping_3d, only: &
25 
26  use sll_m_matrix_csr, only: &
28 
29  use sll_m_maxwell_clamped_3d_trafo, only : &
31 
32  use mpi, only: &
33  mpi_sum
34 
35  use sll_m_profile_functions, only: &
37 
41 
45 
49 
50  use sll_m_splines_pp, only: &
52 
55 
56  implicit none
57 
58  public :: &
60 
61  private
62  !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
63 
65 
66  contains
67 
68  procedure :: &
69  init => init_3d_trafo_parallel
70 
72 
73 contains
74 
75 
76 
77  subroutine init_3d_trafo_parallel( self, domain, n_cells, s_deg_0, boundary, map, mass_tolerance, poisson_tolerance, solver_tolerance, adiabatic_electrons, profile )
78  class(sll_t_maxwell_clamped_3d_trafo_parallel), intent( inout ) :: self
79  sll_real64, intent(in) :: domain(3,2)
80  sll_int32, intent( in ) :: n_cells(3)
81  sll_int32, intent( in ) :: s_deg_0(3)
82  sll_int32, intent( in ) :: boundary(3)
83  type(sll_t_mapping_3d), target, intent( inout ) :: map
84  sll_real64, intent(in), optional :: mass_tolerance
85  sll_real64, intent(in), optional :: poisson_tolerance
86  sll_real64, intent(in), optional :: solver_tolerance
87  logical, intent(in), optional :: adiabatic_electrons
88  type(sll_t_profile_functions), intent(in), optional :: profile
89  ! local variables
90  sll_int32 :: mpi_rank
91  sll_int32 :: mpi_total
92  sll_int32 :: begin(3)
93  sll_int32 :: limit(3)
94  sll_int32 :: j, deg1(3), deg2(3)
95  type(sll_t_matrix_csr) :: mass0_local
96  type(sll_t_matrix_csr) :: mass1_local(3,3)
97  type(sll_t_matrix_csr) :: mass2_local(3,3)
98 
99  self%Lx = map%Lx
100 
101  if (present( mass_tolerance) ) then
102  self%mass_solver_tolerance = mass_tolerance
103  else
104  self%mass_solver_tolerance = 1d-12
105  end if
106  if (present( poisson_tolerance) ) then
107  self%poisson_solver_tolerance = poisson_tolerance
108  else
109  self%poisson_solver_tolerance = 1d-12
110  end if
111  if (present( solver_tolerance) ) then
112  self%solver_tolerance = solver_tolerance
113  else
114  self%solver_tolerance = 1d-12
115  end if
116 
117  if( present( adiabatic_electrons ) ) then
118  self%adiabatic_electrons = adiabatic_electrons
119  end if
120 
121  if( present( profile ) ) then
122  self%profile = profile
123  end if
124 
125  self%n_cells = n_cells
126  self%n_dofs = n_cells
127  self%n_dofs(1) = n_cells(1)+s_deg_0(1)
128  self%n_total = product(n_cells)
129  self%n_total0 = product(self%n_dofs)
130  self%n_total1 = (self%n_dofs(1)-1)*n_cells(2)*n_cells(3)
131  self%delta_x = 1._f64 / real(n_cells,f64)
132  self%s_deg_0 = s_deg_0
133  self%s_deg_1 = s_deg_0 - 1
134  self%volume = product(self%delta_x)
135  self%map => map
136 
137  allocate( self%spline0_pp )
138  allocate( self%spline1_pp )
139  call sll_s_spline_pp_init_1d( self%spline0_pp, s_deg_0(1), self%n_cells(1), boundary(1))
140  call sll_s_spline_pp_init_1d( self%spline1_pp, s_deg_0(1)-1, self%n_cells(1), boundary(1))
141 
142  ! Allocate scratch data
143  allocate(self%work0(1:self%n_total0))
144  allocate(self%work01(1:self%n_total0))
145  allocate(self%work02(1:self%n_total0))
146  allocate(self%work1(1:self%n_total1+2*self%n_total0))
147  allocate(self%work12(1:self%n_total1+2*self%n_total0))
148  allocate(self%work2(1:self%n_total0+2*self%n_total1))
149  allocate(self%work22(1:self%n_total0+2*self%n_total1))
150 
151 
154 
155 
156  call sll_s_compute_mpi_decomposition( mpi_rank, mpi_total, n_cells, begin, limit )
157 
158 !!!!! Assemble the sparse diagonal mass matrices
159  !0-form
160  deg1 = self%s_deg_0
161  if(self%adiabatic_electrons) then
162  call sll_s_spline_fem_mass3d_clamped( self%n_cells, deg1, 0, mass0_local, profile_m0, self%spline0_pp, begin, limit )
163  else
164  call sll_s_spline_fem_mass3d_clamped( self%n_cells, deg1, 0, mass0_local, profile_0, self%spline0_pp, begin, limit )
165  end if
166  ! first diagonal entry
167  deg1(1) = self%s_deg_1(1)
168  if(deg1(1) == 0 ) then
169  call sll_s_spline_fem_mass3d( self%n_cells, deg1, 1, mass1_local(1,1), profile_1, begin, limit )
170  else
171  call sll_s_spline_fem_mass3d_clamped( self%n_cells, deg1, 1, mass1_local(1,1), profile_1, self%spline1_pp, begin, limit )
172  end if
173  deg1 = self%s_deg_1
174  deg1(1) = self%s_deg_0(1)
175  call sll_s_spline_fem_mass3d_clamped( self%n_cells, deg1, 1, mass2_local(1,1), profile_2, self%spline0_pp, begin, limit )
176  !second and third diagonal entry
177  do j = 2, 3
178  deg1 = self%s_deg_0
179  deg1(j) = self%s_deg_1(j)
180  call sll_s_spline_fem_mass3d_clamped( self%n_cells, deg1, j, mass1_local(j,j), profile_1, self%spline0_pp, begin, limit )
181 
182  deg1 = self%s_deg_1
183  deg1(j) = self%s_deg_0(j)
184  if(deg1(1) == 0 ) then
185  call sll_s_spline_fem_mass3d( self%n_cells, deg1, j, mass2_local(j,j), profile_2, begin, limit )
186  else
187  call sll_s_spline_fem_mass3d_clamped( self%n_cells, deg1, j, mass2_local(j,j), profile_2, self%spline1_pp, begin, limit )
188  end if
189  end do
190 !!!!!!!!
191 
192 !!!!assemble mixed mass for one differential form( 1 or 2 )
193  if(self%map%flag2d )then
194  !off diagonal entries for the upper 2x2 submatrix
195  deg1 = self%s_deg_0
196  deg1(1) = self%s_deg_1(1)
197  deg2 = self%s_deg_0
198  deg2(2) = self%s_deg_1(2)
199  call sll_s_spline_fem_mixedmass3d_clamped( self%n_cells,deg1,deg2,[1,2], mass1_local(1,2), profile_m1, self%spline1_pp, self%spline0_pp, begin, limit )
200  call sll_s_spline_fem_mixedmass3d_clamped( self%n_cells,deg2,deg1,[2,1],mass1_local(2,1), profile_m1, self%spline0_pp, self%spline1_pp, begin, limit )
201  deg1 = self%s_deg_1
202  deg1(1) = self%s_deg_0(1)
203  deg2 = self%s_deg_1
204  deg2(2) = self%s_deg_0(2)
205  call sll_s_spline_fem_mixedmass3d_clamped( self%n_cells, deg1, deg2, [1,2], mass2_local(1,2), profile_m2, self%spline0_pp, self%spline1_pp, begin, limit )
206  call sll_s_spline_fem_mixedmass3d_clamped( self%n_cells, deg2, deg1, [2,1], mass2_local(2,1), profile_m2, self%spline1_pp, self%spline0_pp, begin, limit )
207  if(self%map%flag3d)then
208  ! off diagonal entries for the full 3d matrix
209  deg1=self%s_deg_0
210  deg1(2)=self%s_deg_1(2)
211  deg2=self%s_deg_0
212  deg2(3) = self%s_deg_1(3)
213  call sll_s_spline_fem_mixedmass3d_clamped( self%n_cells,deg1,deg2,[2,3],mass1_local(2,3), profile_m1, self%spline0_pp, self%spline0_pp, begin, limit )
214  call sll_s_spline_fem_mixedmass3d_clamped( self%n_cells,deg2,deg1,[3,2],mass1_local(3,2), profile_m1, self%spline0_pp, self%spline0_pp, begin, limit )
215  deg1 = self%s_deg_1
216  deg1(2) = self%s_deg_0(2)
217  deg2 = self%s_deg_1
218  deg2(3) = self%s_deg_0(3)
219  if(deg1(1) == 0 .and. deg2(1) == 0) then
220  call sll_s_spline_fem_mixedmass3d( self%n_cells,deg1,deg2,[2,3],mass2_local(2,3), profile_m2, begin, limit )
221  call sll_s_spline_fem_mixedmass3d( self%n_cells,deg2,deg1,[3,2],mass2_local(3,2), profile_m2, begin, limit )
222  else
223  call sll_s_spline_fem_mixedmass3d_clamped( self%n_cells,deg1,deg2,[2,3],mass2_local(2,3), profile_m2, self%spline1_pp, self%spline1_pp, begin, limit )
224  call sll_s_spline_fem_mixedmass3d_clamped( self%n_cells,deg2,deg1,[3,2],mass2_local(3,2), profile_m2, self%spline1_pp, self%spline1_pp, begin, limit )
225  end if
226  deg1=self%s_deg_0
227  deg1(3)=self%s_deg_1(3)
228  deg2=self%s_deg_0
229  deg2(1) = self%s_deg_1(1)
230  call sll_s_spline_fem_mixedmass3d_clamped( self%n_cells,deg1,deg2,[3,1],mass1_local(3,1), profile_m1, self%spline0_pp, self%spline1_pp, begin, limit )
231  call sll_s_spline_fem_mixedmass3d_clamped( self%n_cells,deg2,deg1,[1,3],mass1_local(1,3), profile_m1, self%spline1_pp, self%spline0_pp, begin, limit )
232  deg1 = self%s_deg_1
233  deg1(3) = self%s_deg_0(3)
234  deg2 = self%s_deg_1
235  deg2(1) = self%s_deg_0(1)
236  call sll_s_spline_fem_mixedmass3d_clamped( self%n_cells,deg1,deg2,[3,1],mass2_local(3,1), profile_m2, self%spline1_pp, self%spline0_pp, begin, limit )
237  call sll_s_spline_fem_mixedmass3d_clamped( self%n_cells,deg2,deg1,[1,3],mass2_local(1,3), profile_m2, self%spline0_pp, self%spline1_pp, begin, limit )
238  end if
239  end if
240 
241  !initialize global matrices
242  deg1=self%s_deg_0
243  call sll_s_spline_fem_sparsity_mass3d_clamped( deg1, n_cells, self%mass0 )
244  do j=1, 3
245  deg1=self%s_deg_0
246  deg1(j)=self%s_deg_1(j)
247  deg2=self%s_deg_0
248  deg2(modulo(j,3)+1) = self%s_deg_1(modulo(j,3)+1)
249  call sll_s_spline_fem_sparsity_mass3d_clamped( deg1, n_cells, self%mass1(j,j) )
250  call sll_s_spline_fem_sparsity_mixedmass3d_clamped( deg1, deg2, n_cells, self%mass1(j,modulo(j,3)+1) )
251  call sll_s_spline_fem_sparsity_mixedmass3d_clamped( deg2, deg1, n_cells, self%mass1(modulo(j,3)+1,j) )
252  deg1 = self%s_deg_1
253  deg1(j) = self%s_deg_0(j)
254  deg2 = self%s_deg_1
255  deg2(modulo(j,3)+1) = self%s_deg_0(modulo(j,3)+1)
256  call sll_s_spline_fem_sparsity_mass3d_clamped( deg1, n_cells, self%mass2(j,j) )
257  call sll_s_spline_fem_sparsity_mixedmass3d_clamped( deg1, deg2, n_cells, self%mass2(j,modulo(j,3)+1) )
258  call sll_s_spline_fem_sparsity_mixedmass3d_clamped( deg2, deg1, n_cells, self%mass2(modulo(j,3)+1,j) )
259  end do
260 
261  ! MPI to sum up contributions from each processor
262  call sll_o_collective_allreduce( sll_v_world_collective, mass0_local%arr_a(1,:), &
263  self%mass0%n_nnz, mpi_sum, self%mass0%arr_a(1,:))
264 
265  do j=1, 3
266  call sll_o_collective_allreduce( sll_v_world_collective, mass1_local(j,j)%arr_a(1,:), &
267  self%mass1(j,j)%n_nnz, mpi_sum, self%mass1(j,j)%arr_a(1,:))
268  call sll_o_collective_allreduce( sll_v_world_collective, mass2_local(j,j)%arr_a(1,:), &
269  self%mass2(j,j)%n_nnz, mpi_sum, self%mass2(j,j)%arr_a(1,:))
270  end do
271 
272  if(self%map%flag2d)then
273  call sll_o_collective_allreduce( sll_v_world_collective, mass1_local(1,2)%arr_a(1,:), &
274  self%mass1(1,2)%n_nnz, mpi_sum, self%mass1(1,2)%arr_a(1,:))
275  call sll_o_collective_allreduce( sll_v_world_collective, mass1_local(2,1)%arr_a(1,:), &
276  self%mass1(2,1)%n_nnz, mpi_sum, self%mass1(2,1)%arr_a(1,:))
277  call sll_o_collective_allreduce( sll_v_world_collective, mass2_local(1,2)%arr_a(1,:), &
278  self%mass2(1,2)%n_nnz, mpi_sum, self%mass2(1,2)%arr_a(1,:))
279  call sll_o_collective_allreduce( sll_v_world_collective, mass2_local(2,1)%arr_a(1,:), &
280  self%mass2(2,1)%n_nnz, mpi_sum, self%mass2(2,1)%arr_a(1,:))
281  if(self%map%flag3d)then
282  do j = 2, 3
283  call sll_o_collective_allreduce( sll_v_world_collective, mass1_local(j,modulo(j,3)+1)%arr_a(1,:), &
284  self%mass1(j,modulo(j,3)+1)%n_nnz, mpi_sum, self%mass1(j,modulo(j,3)+1)%arr_a(1,:))
285  call sll_o_collective_allreduce( sll_v_world_collective, mass1_local(modulo(j,3)+1,j)%arr_a(1,:), &
286  self%mass1(modulo(j,3)+1,j)%n_nnz, mpi_sum, self%mass1(modulo(j,3)+1,j)%arr_a(1,:))
287  call sll_o_collective_allreduce( sll_v_world_collective, mass2_local(j,modulo(j,3)+1)%arr_a(1,:), &
288  self%mass2(j,modulo(j,3)+1)%n_nnz, mpi_sum, self%mass2(j,modulo(j,3)+1)%arr_a(1,:))
289  call sll_o_collective_allreduce( sll_v_world_collective, mass2_local(modulo(j,3)+1,j)%arr_a(1,:), &
290  self%mass2(modulo(j,3)+1,j)%n_nnz, mpi_sum, self%mass2(modulo(j,3)+1,j)%arr_a(1,:))
291  end do
292  end if
293  end if
294 
295 
296  call self%mass1_operator%create( 3, 3 )
297  call self%mass2_operator%create( 3, 3 )
298 
299  do j=1,3
300  call self%mass1_operator%set( j, j, self%mass1(j,j) )
301  call self%mass2_operator%set( j, j, self%mass2(j,j) )
302  end do
303  if(self%map%flag2d)then
304  call self%mass1_operator%set( 1, 2, self%mass1(1,2) )
305  call self%mass1_operator%set( 2, 1, self%mass1(2,1) )
306  call self%mass2_operator%set( 1, 2, self%mass2(1,2) )
307  call self%mass2_operator%set( 2, 1, self%mass2(2,1) )
308  if(self%map%flag3d)then
309  do j = 2, 3
310  call self%mass1_operator%set( j, modulo(j,3)+1, self%mass1(j,modulo(j,3)+1) )
311  call self%mass1_operator%set( modulo(j,3)+1, j, self%mass1(modulo(j,3)+1,j) )
312  call self%mass2_operator%set( j, modulo(j,3)+1, self%mass2(j,modulo(j,3)+1) )
313  call self%mass2_operator%set( modulo(j,3)+1, j, self%mass2(modulo(j,3)+1,j) )
314  end do
315  end if
316  end if
317 
318  call self%preconditioner_fft%init( self%Lx, n_cells, s_deg_0, .true. )
319 
320  self%work12 = 1._f64
321  call self%mass1_operator%dot(self%work12, self%work1)
322  do j = 1, self%n_dofs(2)*self%n_dofs(3)
323  self%work1(self%n_total1+1+(j-1)*self%n_dofs(1)) = 1._f64
324  self%work1(self%n_total1+j*self%n_dofs(1)) = 1._f64
325  self%work1(self%n_total1+self%n_total0+1+(j-1)*self%n_dofs(1)) = 1._f64
326  self%work1(self%n_total1+self%n_total0+j*self%n_dofs(1)) = 1._f64
327  end do
328  self%work1 = 1._f64/sqrt(abs(self%work1))
329 
330  self%work22 = 1._f64
331  call self%mass2_operator%dot(self%work22, self%work2)
332  do j = 1, self%n_dofs(2)*self%n_dofs(3)
333  self%work2(1+(j-1)*self%n_dofs(1)) = 1._f64
334  self%work2(j*self%n_dofs(1)) = 1._f64
335  end do
336  self%work2 = 1._f64/sqrt(abs(self%work2))
337  call self%preconditioner1%create( self%preconditioner_fft%inverse_mass1_3d, self%work1, 2*self%n_total0+self%n_total1 )
338  call self%preconditioner2%create( self%preconditioner_fft%inverse_mass2_3d, self%work2, 2*self%n_total1+self%n_total0 )
339 
340 
341  self%work0 = 0._f64
342  self%work01 = 0._f64
343  self%work1 = 0._f64
344  self%work12 = 0._f64
345  self%work2 = 0._f64
346  self%work22 = 0._f64
347 
348  call self%mass0_solver%create( self%mass0 )
349  call self%mass1_solver%create( self%mass1_operator, self%preconditioner1)
350  call self%mass2_solver%create( self%mass2_operator, self%preconditioner2)
351  self%mass0_solver%atol = self%mass_solver_tolerance
352  self%mass1_solver%atol = self%mass_solver_tolerance/maxval(self%Lx)
353  self%mass2_solver%atol = self%mass_solver_tolerance/maxval(self%Lx)**2
354  !self%mass0_solver%verbose = .true.
355  !self%mass1_solver%verbose = .true.
356  !self%mass2_solver%verbose = .true.
357 
358 
359  call self%poisson_matrix%create( self%mass1_operator, self%s_deg_0, self%n_dofs, self%delta_x)
360 
361  ! Preconditioner for Poisson solver based on FFT inversion for periodic case
362 
363  do j= 1, self%n_total0
364  self%work01 = 0._f64
365  self%work01(j) = 1._f64
366  call self%mass0%dot( self%work01, self%work02 )
367  if (abs(self%work02(j))< 1d-13) then
368  self%work0(j) = 1._f64
369  else
370  self%work0(j) = 1._f64/sqrt(self%work02(j))
371  end if
372  end do
373 
374  call self%poisson_preconditioner%create( self%n_dofs, self%s_deg_0, self%delta_x, self%work0 )
375  call self%poisson_solver%create( self%poisson_matrix, self%poisson_preconditioner )
376  self%poisson_solver%atol = self%poisson_solver_tolerance
377  !self%poisson_solver%verbose = .true.
378 
379  self%work0 = 0._f64
380  self%work01 = 0._f64
381 
382  ! Only for Schur complement eb solver
383  call self%linear_op_schur_eb%create( self%mass1_operator, self%mass2_operator, self%n_dofs, self%delta_x, self%s_deg_0 )
384  call self%linear_solver_schur_eb%create( self%linear_op_schur_eb, self%preconditioner1 )
385  self%linear_solver_schur_eb%atol = self%solver_tolerance
386  !self%linear_solver_schur_eb%verbose = .true.
387  !self%linear_solver_schur_eb%n_maxiter = 2000
388 
389  contains
390  function profile_m0( x, component)
391  sll_real64 :: profile_m0
392  sll_real64, intent(in) :: x(3)
393  sll_int32, optional, intent(in) :: component(:)
394 
395  profile_m0 = self%map%jacobian( x ) * self%profile%rho_0( x(1) )/ self%profile%T_e( x(1) )
396 
397  end function profile_m0
398 
399  function profile_0(x, component)
400  sll_real64 :: profile_0
401  sll_real64, intent(in) :: x(3)
402  sll_int32, optional, intent(in) :: component(:)
403 
404  profile_0 = self%map%jacobian( x )
405 
406  end function profile_0
407 
408  function profile_1(x, component)
409  sll_real64 :: profile_1
410  sll_real64, intent(in) :: x(3)
411  sll_int32, optional, intent(in) :: component(:)
412 
413  profile_1 = self%map%metric_inverse_single_jacobian( x, component(1), component(1) )
414 
415  end function profile_1
416 
417  function profile_2(x, component)
418  sll_real64 :: profile_2
419  sll_real64, intent(in) :: x(3)
420  sll_int32, optional, intent(in) :: component(:)
421 
422  profile_2 = self%map%metric_single_jacobian( x, component(1), component(1) )
423 
424  end function profile_2
425 
426  function profile_m1(x, component)
427  sll_real64 :: profile_m1
428  sll_real64, intent(in) :: x(3)
429  sll_int32, optional, intent(in) :: component(:)
430 
431  profile_m1 = self%map%metric_inverse_single_jacobian( x, component(1), component(2) )
432  end function profile_m1
433 
434  function profile_m2(x, component)
435  sll_real64 :: profile_m2
436  sll_real64, intent(in) :: x(3)
437  sll_int32, optional, intent(in) :: component(:)
438 
439  profile_m2 = self%map%metric_single_jacobian( x, component(1), component(2) )
440 
441  end function profile_m2
442 
443  end subroutine init_3d_trafo_parallel
444 
445 
446  subroutine sll_s_compute_mpi_decomposition( mpi_rank, mpi_total, n_cells, begin, limit )
447  sll_int32, intent( in ) :: mpi_rank
448  sll_int32, intent( in ) :: mpi_total
449  sll_int32, intent( in ) :: n_cells(3)
450  sll_int32, intent( out ) :: begin(3)
451  sll_int32, intent( out ) :: limit(3)
452 
453  if( mpi_total <= n_cells(3) )then
454  begin(3)=1+mpi_rank*n_cells(3)/mpi_total
455  limit(3)=(mpi_rank+1)*n_cells(3)/mpi_total
456  if( mpi_rank == mpi_total-1 ) then
457  limit(3)=n_cells(3)
458  end if
459  begin(2)=1
460  limit(2)=n_cells(2)
461  else if( mpi_total > n_cells(3) .and. mpi_total < n_cells(2)*n_cells(3) ) then
462  if(modulo(real(n_cells(3)*n_cells(2),f64)/real(mpi_total,f64),1._f64)==0 )then
463  begin(3)=1+mpi_rank*n_cells(3)/mpi_total
464  limit(3)=begin(3)
465  begin(2)=1+modulo((mpi_rank*n_cells(2)*n_cells(3))/mpi_total, n_cells(2))
466  limit(2)=modulo(((mpi_rank+1)*n_cells(2)*n_cells(3))/mpi_total-1,n_cells(2))+1
467  else
468  print*, 'bad amount of mpi processes'
469  if( mpi_rank < n_cells(3) ) then
470  begin(3)=1+mpi_rank
471  limit(3)=begin(3)
472  begin(2)=1
473  limit(2)=n_cells(2)
474  else
475  begin(3)=1
476  limit(3)=0
477  begin(2)=1
478  limit(2)=0
479  end if
480  end if
481  else
482  if( mpi_rank < n_cells(2)*n_cells(3) )then
483  begin(3)=1+mpi_rank/n_cells(2)
484  limit(3)=begin(3)
485  begin(2)=1+modulo(mpi_rank,n_cells(2))
486  limit(2)=begin(2)
487  else
488  begin(3)=1
489  limit(3)=0
490  begin(2)=1
491  limit(2)=0
492  end if
493  end if
494  begin(1)=1
495  limit(1)=n_cells(1)
496 
497  end subroutine sll_s_compute_mpi_decomposition
498 
499 
Combines values from all processes and distributes the result back to all processes.
Parallelizing facility.
integer(kind=i32) function, public sll_f_get_collective_rank(col)
Determines the rank of the calling process in the communicator.
subroutine, public sll_s_collective_reduce_real64(col, send_buf, size, op, root_rank, rec_buf)
type(sll_t_collective_t), pointer, public sll_v_world_collective
Control of subset assignment. Processes with the same color are in the same new communicator.
integer(kind=i32) function, public sll_f_get_collective_size(col)
Determines the size of the group associated with a communicator.
Module interfaces for coordinate transformation.
module for Compressed Sparse Row Matrix (CSR)
Module interface to solve Maxwell's equations with coordinate transformation in 3D.
subroutine init_3d_trafo_parallel(self, domain, n_cells, s_deg_0, boundary, map, mass_tolerance, poisson_tolerance, solver_tolerance, adiabatic_electrons, profile)
subroutine sll_s_compute_mpi_decomposition(mpi_rank, mpi_total, n_cells, begin, limit)
Module interface to solve Maxwell's equations with coordinate transformation in 3D.
This module is a wrapper around the spline FEM Poisson solver for the uniform grid with periodic boun...
functions for initial profile of the particle distribution function
Utilites for Maxwell solver's with spline finite elements using sparse matrices.
subroutine, public sll_s_spline_fem_mixedmass3d_clamped(n_cells, deg1, deg2, component, matrix, profile, spline1, spline2, n_cells_min, n_cells_max)
Set up 3d clamped mixed mass matrix for specific spline degree and profile function.
subroutine, public sll_s_spline_fem_mass3d_clamped(n_cells, deg, component, matrix, profile, spline, n_cells_min, n_cells_max)
Set up 3d clamped mass matrix for specific spline degrees and profile function.
Helper for spline finite elements utilites.
subroutine, public sll_s_spline_fem_sparsity_mixedmass3d_clamped(deg1, deg2, n_cells, spmat)
Helper function to create sparsity pattern of the 3d clamped mixed mass matrix.
subroutine, public sll_s_spline_fem_sparsity_mass3d_clamped(deg, n_cells, spmat)
Helper function to create sparsity pattern of the 3d clamped mass matrix.
Utilites for 3D Maxwell solvers with spline finite elements.
subroutine, public sll_s_spline_fem_mass3d(n_cells, deg, component, matrix, profile, n_cells_min, n_cells_max)
Set up 3d mass matrix for specific spline degrees and profile function.
subroutine, public sll_s_spline_fem_mixedmass3d(n_cells, deg1, deg2, component, matrix, profile, n_cells_min, n_cells_max)
Set up 3d mixed mass matrix for specific spline degree and profile function.
Splines in pp form.
subroutine, public sll_s_spline_pp_init_1d(self, degree, n_cells, boundary)
Initialize sll_t_spline_pp_1d object (Set poly_coeffs depending on degree)
real(kind=f64) function profile_0(x)
real(kind=f64) function profile_m0(x)
real(kind=f64) function profile_1(x)
real(kind=f64) function profile_m2(x, component)
real(kind=f64) function profile_2(x, component)
real(kind=f64) function profile_m1(x, component)
type collecting functions for analytical coordinate mapping
    Report Typos and Errors