27 #include "sll_assert.h"
28 #include "sll_errors.h"
29 #include "sll_memory.h"
30 #include "sll_working_precision.h"
80 sll_int32 :: n_particles_x
81 sll_int32 :: n_particles_y
82 sll_int32 :: n_particles_vx
83 sll_int32 :: n_particles_vy
84 sll_real64,
allocatable :: particle_array(:,:)
85 sll_real64 :: common_weight
95 logical :: domain_is_periodic(2)
101 sll_int32 :: remapped_f_interpolation_degree
103 sll_int32,
dimension(4) :: sparse_grid_max_levels
104 sll_real64,
dimension(:),
allocatable :: remapped_f_sparse_grid_coefficients
105 sll_real64,
dimension(:),
allocatable :: tmp_f_values_on_remapping_sparse_grid
162 sll_int32 ,
intent( in ) :: i
166 r(1:2) = self%particle_array(1:2, i)
174 sll_int32 ,
intent( in ) :: i
178 r(1:2) = self%particle_array(3:4, i)
188 sll_int32 ,
intent( in ) :: i
189 sll_int32,
optional ,
intent( in ) :: i_weight
195 if(
present(i_weight)) i_wi = i_weight
196 r = self%species%q * self%particle_array(4+i_wi, i) * self%common_weight
205 sll_int32 ,
intent( in ) :: i
206 sll_int32,
optional ,
intent( in ) :: i_weight
212 if(
present(i_weight)) i_wi = i_weight
213 r = self%species%m * self%particle_array(4+i_wi, i) * self%common_weight
222 sll_int32 ,
intent( in ) :: i
223 sll_real64 :: r(self%n_weights)
225 r = self%particle_array(5:4+self%n_weights, i)
235 r = self%common_weight
245 sll_int32 ,
intent( in ) :: i
246 sll_real64 ,
intent( in ) :: x(3)
248 self%particle_array(1:2, i) = x(1:2)
256 sll_int32 ,
intent( in ) :: i
257 sll_real64 ,
intent( in ) :: x(3)
259 self%particle_array(3:4, i) = x(1:2)
267 sll_int32 ,
intent( in ) :: i
268 sll_real64 ,
intent( in ) :: x(self%n_weights)
270 self%particle_array(5:4+self%n_weights, i) = x
278 sll_real64 ,
intent( in ) :: x
280 self%common_weight = x
291 domain_is_x_periodic, &
292 domain_is_y_periodic, &
294 remapping_grid_eta_min, &
295 remapping_grid_eta_max, &
296 remapping_sparse_grid_max_levels, &
306 sll_real64,
intent(in) :: species_charge
307 sll_real64,
intent(in) :: species_mass
308 logical,
intent(in) :: domain_is_x_periodic
309 logical,
intent(in) :: domain_is_y_periodic
310 sll_int32,
intent(in) :: remap_degree
311 sll_real64,
dimension(4),
intent(in) :: remapping_grid_eta_min
312 sll_real64,
dimension(4),
intent(in) :: remapping_grid_eta_max
313 sll_int32,
dimension(4),
intent(in) :: remapping_sparse_grid_max_levels
314 sll_int32,
intent(in) :: n_particles_x
315 sll_int32,
intent(in) :: n_particles_y
316 sll_int32,
intent(in) :: n_particles_vx
317 sll_int32,
intent(in) :: n_particles_vy
318 sll_int32,
intent(in) :: n_weights
320 character(len=*),
parameter :: this_fun_name =
"initialize_particle_group_2d2v_lbf"
323 print*,
"[", this_fun_name,
"] - initializing the particle group... "
325 self%domain_is_periodic(1) = domain_is_x_periodic
326 self%domain_is_periodic(2) = domain_is_y_periodic
328 self%n_particles_x = n_particles_x
329 self%n_particles_y = n_particles_y
330 self%n_particles_vx = n_particles_vx
331 self%n_particles_vy = n_particles_vy
332 self%n_particles = n_particles_x * n_particles_y * n_particles_vx * n_particles_vy
333 self%n_total_particles = self%n_particles
334 self%n_weights = n_weights
337 allocate(self%species, stat=ierr)
338 sll_assert( ierr == 0)
339 call self%species%init( species_charge, species_mass )
341 sll_allocate( self%particle_array(4+n_weights, self%n_particles), ierr)
342 sll_assert( ierr == 0)
352 remapping_grid_eta_min(1), &
353 remapping_grid_eta_max(1), &
354 remapping_grid_eta_min(2), &
355 remapping_grid_eta_max(2), &
356 remapping_grid_eta_min(3), &
357 remapping_grid_eta_max(3), &
358 remapping_grid_eta_min(4), &
359 remapping_grid_eta_max(4) )
362 self%remapped_f_interpolation_degree = remap_degree
364 print*,
"[", this_fun_name,
"] - sparse grid levels for the remapping tool:", remapping_sparse_grid_max_levels
365 self%sparse_grid_max_levels = remapping_sparse_grid_max_levels
366 call self%sparse_grid_interpolator%init( &
367 self%sparse_grid_max_levels, &
368 self%remapped_f_interpolation_degree, &
369 self%remapped_f_interpolation_degree+1, &
371 remapping_grid_eta_min, &
372 remapping_grid_eta_max &
376 sll_allocate( self%remapped_f_sparse_grid_coefficients(self%sparse_grid_interpolator%size_basis), ierr )
377 self%remapped_f_sparse_grid_coefficients = 0.0_f64
380 sll_allocate( self%tmp_f_values_on_remapping_sparse_grid(self%sparse_grid_interpolator%size_basis), ierr)
390 domain_is_x_periodic, &
391 domain_is_y_periodic, &
393 remapping_grid_eta_min, &
394 remapping_grid_eta_max, &
395 remapping_sparse_grid_max_levels, &
402 sll_real64,
intent(in) :: species_charge
403 sll_real64,
intent(in) :: species_mass
404 logical,
intent(in) :: domain_is_x_periodic
405 logical,
intent(in) :: domain_is_y_periodic
406 sll_int32,
intent(in) :: remap_degree
407 sll_real64,
dimension(4),
intent(in) :: remapping_grid_eta_min
408 sll_real64,
dimension(4),
intent(in) :: remapping_grid_eta_max
409 sll_int32,
dimension(4),
intent(in) :: remapping_sparse_grid_max_levels
410 sll_int32,
intent(in) :: n_particles_x
411 sll_int32,
intent(in) :: n_particles_y
412 sll_int32,
intent(in) :: n_particles_vx
413 sll_int32,
intent(in) :: n_particles_vy
416 sll_int32 :: n_weights
421 select type( particle_group )
423 call particle_group%init( &
426 domain_is_x_periodic, &
427 domain_is_y_periodic, &
429 remapping_grid_eta_min, &
430 remapping_grid_eta_max, &
431 remapping_sparse_grid_max_levels, &
446 deallocate(self%particle_array)
447 deallocate(self%remapped_f_sparse_grid_coefficients)
448 deallocate(self%tmp_f_values_on_remapping_sparse_grid)
461 subroutine sample( self, target_total_charge, enforce_total_charge, init_f_params, rand_seed, rank, world_size )
463 sll_real64,
intent( in ) :: target_total_charge
464 logical,
intent( in ) :: enforce_total_charge
466 sll_int32,
dimension(:) ,
intent( in ),
optional :: rand_seed
467 sll_int32 ,
intent( in ),
optional :: rank, world_size
469 if(
present(rand_seed) )
then
470 sll_assert(
present( rank ) )
471 sll_assert(
present( world_size ) )
472 call self%resample( target_total_charge, enforce_total_charge, init_f_params, rand_seed, rank, world_size )
474 call self%resample( target_total_charge, enforce_total_charge, init_f_params )
483 subroutine resample( self, target_total_charge, enforce_total_charge, init_f_params, rand_seed, rank, world_size )
485 sll_real64,
intent( in ) :: target_total_charge
486 logical,
intent( in ) :: enforce_total_charge
488 sll_int32,
dimension(:) ,
intent( in ),
optional :: rand_seed
489 sll_int32 ,
intent( in ),
optional :: rank, world_size
491 logical :: initial_step
493 initial_step =
present(init_f_params)
496 print *,
"particle_group_2d2v_lbf%resample -- step A (LBF approximation of transported density on remapping grid)"
499 if( initial_step )
then
501 call self%write_known_density_on_remapping_grid(init_f_params)
505 call self%reconstruct_f_lbf_on_remapping_grid()
509 call self%sparse_grid_interpolator%compute_hierarchical_surplus( self%tmp_f_values_on_remapping_sparse_grid )
510 self%remapped_f_sparse_grid_coefficients = self%tmp_f_values_on_remapping_sparse_grid
513 print *,
"particle_group_2d2v_lbf%resample -- step B (deterministic resampling of particles using the remapped density)"
514 call self%reset_particles_positions
516 call self%reset_particles_weights_with_direct_interpolation( target_total_charge, enforce_total_charge )
519 if(
present(rank))
then
520 sll_assert(
present(world_size))
521 sll_assert(
present(rand_seed))
530 distribution_params &
537 sll_real64 :: x_j(1:2)
538 sll_real64 :: v_j(1:2)
540 sll_assert(
size(self%tmp_f_values_on_remapping_sparse_grid,1) == self%sparse_grid_interpolator%size_basis )
541 self%tmp_f_values_on_remapping_sparse_grid = 0.0_f64
543 do j=1, self%sparse_grid_interpolator%size_basis
544 x_j = self%sparse_grid_interpolator%hierarchy(j)%coordinate(1:2)
545 v_j = self%sparse_grid_interpolator%hierarchy(j)%coordinate(3:4)
546 self%tmp_f_values_on_remapping_sparse_grid(j) = distribution_params%eval_xv_density( x_j, v_j )
561 sll_real64,
dimension(3) :: coords
580 sll_assert( self%n_particles_x == self%lbf_grid%num_cells1 )
581 sll_assert( self%n_particles_y == self%lbf_grid%num_cells2 )
582 sll_assert( self%n_particles_vx == self%lbf_grid%num_cells3 )
583 sll_assert( self%n_particles_vy == self%lbf_grid%num_cells4 )
585 h_x = self%lbf_grid%delta_eta1
586 h_y = self%lbf_grid%delta_eta2
587 h_vx = self%lbf_grid%delta_eta3
588 h_vy = self%lbf_grid%delta_eta4
590 x_min = self%lbf_grid%eta1_min
591 y_min = self%lbf_grid%eta2_min
592 vx_min = self%lbf_grid%eta3_min
593 vy_min = self%lbf_grid%eta4_min
596 do j_x = 1, self%n_particles_x
597 x_j = x_min + (j_x-0.5) * h_x
599 do j_y = 1, self%n_particles_y
600 y_j = y_min + (j_y-0.5) * h_y
602 do j_vx = 1, self%n_particles_vx
603 vx_j = vx_min + (j_vx-0.5) * h_vx
605 do j_vy = 1, self%n_particles_vy
606 vy_j = vy_min + (j_vy-0.5) * h_vy
608 k_check = k_check + 1
611 j_x, j_y, j_vx, j_vy, &
612 self%n_particles_x, self%n_particles_y, self%n_particles_vx, self%n_particles_vy &
614 sll_assert(k == k_check)
618 call self%set_x( k, coords )
622 call self%set_v( k, coords )
636 sll_int32,
intent(in) :: k
637 sll_int32,
intent(in) :: dim
638 sll_int32,
intent(in) :: dir
648 j_x, j_y, j_vx, j_vy, &
650 self%n_particles_x, self%n_particles_y, &
651 self%n_particles_vx, self%n_particles_vy &
658 if(j_ngb < 1 .or. j_ngb > self%n_particles_x )
then
659 if( self%domain_is_periodic(1) )
then
660 j_ngb = modulo(j_ngb-1, self%n_particles_x)+1
662 sll_assert( (j_x == 1 .and. dir == -1) .or. (j_x == self%n_particles_x .and. dir == 1) )
665 sll_error(
"get_neighbor_index",
"CHECK 1 -- should not be here")
670 j_ngb, j_y, j_vx, j_vy, &
671 self%n_particles_x, self%n_particles_y, &
672 self%n_particles_vx, self%n_particles_vy &
679 if(j_ngb < 1 .or. j_ngb > self%n_particles_y )
then
680 if( self%domain_is_periodic(2) )
then
681 j_ngb = modulo(j_ngb-1, self%n_particles_y)+1
683 sll_assert( (j_y == 1 .and. dir == -1) .or. (j_y == self%n_particles_y .and. dir == 1) )
686 sll_error(
"get_neighbor_index",
"CHECK 2 -- should not be here")
691 j_x, j_ngb, j_vx, j_vy, &
692 self%n_particles_x, self%n_particles_y, &
693 self%n_particles_vx, self%n_particles_vy &
700 if(j_ngb < 1 .or. j_ngb > self%n_particles_vx )
then
702 sll_assert( (j_vx == 1 .and. dir == -1) .or. (j_vx == self%n_particles_vx .and. dir == 1) )
705 sll_error(
"get_neighbor_index",
"CHECK 3 -- should not be here")
709 j_x, j_y, j_ngb, j_vy, &
710 self%n_particles_x, self%n_particles_y, &
711 self%n_particles_vx, self%n_particles_vy &
718 if(j_ngb < 1 .or. j_ngb > self%n_particles_vy )
then
720 sll_assert( (j_vy == 1 .and. dir == -1) .or. (j_vy == self%n_particles_vy .and. dir == 1) )
723 sll_error(
"get_neighbor_index",
"CHECK 4 -- should not be here")
727 j_x, j_y, j_vx, j_ngb, &
728 self%n_particles_x, self%n_particles_y, &
729 self%n_particles_vx, self%n_particles_vy &
734 sll_error(
"get_neighbor_index",
"wrong value for dim")
744 target_total_charge, &
745 enforce_total_charge &
748 sll_real64,
intent( in ) :: target_total_charge
749 logical,
intent( in ) :: enforce_total_charge
752 sll_real64 :: phase_space_volume
753 sll_real64 :: particle_density_factor
754 sll_real64 :: point_density, total_computed_density
755 sll_real64 :: total_computed_charge
756 sll_real64 :: charge_correction_factor
759 call self%set_common_weight(1.0_f64)
761 phase_space_volume = (self%lbf_grid%eta4_max - self%lbf_grid%eta4_min) &
762 * (self%lbf_grid%eta3_max - self%lbf_grid%eta3_min) &
763 * (self%lbf_grid%eta2_max - self%lbf_grid%eta2_min) &
764 * (self%lbf_grid%eta1_max - self%lbf_grid%eta1_min)
765 particle_density_factor = phase_space_volume / self%n_particles
766 total_computed_density = 0.0d0
767 do i_part = 1, self%n_particles
768 eta = self%particle_array(1:4, i_part)
769 point_density = particle_density_factor * self%interpolate_value_of_remapped_f(eta)
770 self%particle_array(5, i_part) = point_density
771 total_computed_density = total_computed_density + point_density
774 if( enforce_total_charge )
then
775 total_computed_charge = self%species%q * total_computed_density
776 if( total_computed_density == 0 )
then
777 print *,
"WARNING (876786587689) -- total computed_density is zero, which is strange..."
778 print *,
" -- (no charge correction in this case) "
780 charge_correction_factor = target_total_charge / total_computed_charge
782 print *,
"[Enforcing charge in reset_particles_weights_with_direct_interpolation] ... "
783 print *,
" ... target_total_charge, total_computed_charge, charge_correction_factor = ", &
784 target_total_charge, total_computed_charge, charge_correction_factor
787 do i_part = 1, self%n_particles
788 self%particle_array(5, i_part) = self%particle_array(5, i_part) * charge_correction_factor
800 sll_real64,
dimension(4),
intent(in) :: eta
803 val = self%sparse_grid_interpolator%interpolate_from_interpolant_value(self%remapped_f_sparse_grid_coefficients, eta)
808 #define UPDATE_CLOSEST_PARTICLE_ARRAYS_USING_NEIGHBOR_CELLS(djx,djy,djvx,djvy) \
810 k_neighbor = closest_particle(j_x+(djx), j_y+(djy), j_vx+(djvx), j_vy+(djvy)); \
812 if(k_neighbor /= 0) then; \
814 coords = self%get_x(k_neighbor) ; \
817 coords = self%get_v(k_neighbor) ; \
822 x - self%lbf_grid%eta1_min, y - self%lbf_grid%eta2_min, vx - self%lbf_grid%eta3_min, vy - self%lbf_grid%eta4_min, \
823 j_x, j_y, j_vx, j_vy, \
829 closest_particle_distance) ; \
846 reconstruction_set_type, &
849 reconstruct_f_on_last_node, &
850 target_total_charge, &
851 enforce_total_charge &
854 sll_int32,
intent(in) :: reconstruction_set_type
855 type(sll_t_cartesian_mesh_4d),
pointer,
intent(in) :: given_grid_4d
856 sll_real64,
dimension(:,:,:,:),
pointer,
intent(inout) :: given_array_4d
857 logical,
intent(in) :: reconstruct_f_on_last_node(4)
858 sll_real64,
intent(in) :: target_total_charge
859 logical,
intent(in) :: enforce_total_charge
861 sll_real64 :: deposited_charge
862 sll_real64 :: charge_correction_factor
865 sll_int32,
dimension(:,:,:,:),
allocatable :: closest_particle
866 sll_real64,
dimension(:,:,:,:),
allocatable :: closest_particle_distance
874 sll_int32 :: k_neighbor
875 sll_int32 :: i_x, i_y, i_vx, i_vy
876 sll_int32 :: j_x, j_y, j_vx, j_vy
877 sll_int32 :: m_x, m_y, m_vx, m_vy
882 sll_int32 :: i_min_vx
883 sll_int32 :: i_min_vy
887 sll_int32 :: i_max_vx
888 sll_int32 :: i_max_vy
890 sll_int32 :: node_index
891 sll_int32 :: k_particle_closest_to_first_corner
894 type(sll_t_cartesian_mesh_4d),
pointer :: g
896 sll_int32 :: g_num_points_x
897 sll_int32 :: g_num_points_y
898 sll_int32 :: g_num_points_vx
899 sll_int32 :: g_num_points_vy
901 sll_real64 :: g_grid_x_min
902 sll_real64 :: g_grid_y_min
903 sll_real64 :: g_grid_vx_min
904 sll_real64 :: g_grid_vy_min
906 sll_real64 :: h_g_grid_x
907 sll_real64 :: h_g_grid_y
908 sll_real64 :: h_g_grid_vx
909 sll_real64 :: h_g_grid_vy
912 sll_real64 :: h_flow_grid_x
913 sll_real64 :: h_flow_grid_y
914 sll_real64 :: h_flow_grid_vx
915 sll_real64 :: h_flow_grid_vy
917 sll_int32 :: flow_grid_num_cells_x
918 sll_int32 :: flow_grid_num_cells_y
919 sll_int32 :: flow_grid_num_cells_vx
920 sll_int32 :: flow_grid_num_cells_vy
922 sll_real64 :: flow_grid_x_min
923 sll_real64 :: flow_grid_y_min
924 sll_real64 :: flow_grid_vx_min
925 sll_real64 :: flow_grid_vy_min
927 sll_int32 :: flow_grid_j_x_min
928 sll_int32 :: flow_grid_j_x_max
929 sll_int32 :: flow_grid_j_y_min
930 sll_int32 :: flow_grid_j_y_max
931 sll_int32 :: flow_grid_j_vx_min
932 sll_int32 :: flow_grid_j_vx_max
933 sll_int32 :: flow_grid_j_vy_min
934 sll_int32 :: flow_grid_j_vy_max
941 sll_real64 :: closest_particle_distance_to_first_corner
942 sll_real64 :: particle_distance_to_first_corner
944 sll_real64 :: mesh_period_x
945 sll_real64 :: mesh_period_y
948 sll_real64 :: d11,d12,d13,d14
949 sll_real64 :: d21,d22,d23,d24
950 sll_real64 :: d31,d32,d33,d34
951 sll_real64 :: d41,d42,d43,d44
953 sll_real64,
dimension(3) :: coords
954 sll_real64,
dimension(4) :: eta
957 sll_real64 :: x_k,y_k,vx_k,vy_k
958 sll_real64 :: x_k_t0,y_k_t0,vx_k_t0,vy_k_t0
960 sll_real64 :: x_to_xk, y_to_yk, vx_to_vxk, vy_to_vyk
962 sll_real64 :: d1_x, d1_y, d1_vx, d1_vy
963 sll_real64 :: d2_x, d2_y, d2_vx, d2_vy
964 sll_real64 :: d3_x, d3_y, d3_vx, d3_vy
965 sll_real64 :: d4_x, d4_y, d4_vx, d4_vy
967 sll_int32 :: nodes_number
968 sll_real64 :: reconstructed_f_value
977 sll_real64 :: x_t0_to_xk_t0
978 sll_real64 :: y_t0_to_yk_t0
979 sll_real64 :: vx_t0_to_vxk_t0
980 sll_real64 :: vy_t0_to_vyk_t0
985 flow_grid_x_min = self%lbf_grid%eta1_min
986 flow_grid_y_min = self%lbf_grid%eta2_min
987 flow_grid_vx_min = self%lbf_grid%eta3_min
988 flow_grid_vy_min = self%lbf_grid%eta4_min
990 h_flow_grid_x = self%lbf_grid%delta_eta1
991 h_flow_grid_y = self%lbf_grid%delta_eta2
992 h_flow_grid_vx = self%lbf_grid%delta_eta3
993 h_flow_grid_vy = self%lbf_grid%delta_eta4
995 flow_grid_num_cells_x = self%lbf_grid%num_cells1
996 flow_grid_num_cells_y = self%lbf_grid%num_cells2
997 flow_grid_num_cells_vx = self%lbf_grid%num_cells3
998 flow_grid_num_cells_vy = self%lbf_grid%num_cells4
1002 flow_grid_j_x_min = 1
1003 flow_grid_j_x_max = flow_grid_num_cells_x
1004 flow_grid_j_y_min = 1
1005 flow_grid_j_y_max = flow_grid_num_cells_y
1006 flow_grid_j_vx_min = 1
1007 flow_grid_j_vx_max = flow_grid_num_cells_vx
1008 flow_grid_j_vy_min = 1
1009 flow_grid_j_vy_max = flow_grid_num_cells_vy
1011 deposited_charge = 0.0_f64
1017 allocate(nodes_in_flow_cell(flow_grid_num_cells_x, &
1018 flow_grid_num_cells_y, &
1019 flow_grid_num_cells_vx, &
1020 flow_grid_num_cells_vy) &
1022 call sll_s_test_error_code(ierr,
'Memory allocation Failure.', __file__, __line__)
1024 do j_x = 1, flow_grid_num_cells_x
1025 do j_y = 1, flow_grid_num_cells_y
1026 do j_vx = 1, flow_grid_num_cells_vx
1027 do j_vy = 1, flow_grid_num_cells_vy
1028 nullify(nodes_in_flow_cell(j_x,j_y,j_vx,j_vy)%pointed_element)
1034 nodes_number = self%sparse_grid_interpolator%size_basis
1035 sll_assert(
size(self%tmp_f_values_on_remapping_sparse_grid,1) == nodes_number )
1036 self%tmp_f_values_on_remapping_sparse_grid = 0.0_f64
1039 do node_index = 1, nodes_number
1042 x = self%sparse_grid_interpolator%hierarchy(node_index)%coordinate(1)
1043 y = self%sparse_grid_interpolator%hierarchy(node_index)%coordinate(2)
1044 vx = self%sparse_grid_interpolator%hierarchy(node_index)%coordinate(3)
1045 vy = self%sparse_grid_interpolator%hierarchy(node_index)%coordinate(4)
1054 if( j_x >= flow_grid_j_x_min .and. j_x <= flow_grid_j_x_max .and. &
1055 j_y >= flow_grid_j_y_min .and. j_y <= flow_grid_j_y_max .and. &
1056 j_vx >= flow_grid_j_vx_min .and. j_vx <= flow_grid_j_vx_max .and. &
1057 j_vy >= flow_grid_j_vy_min .and. j_vy <= flow_grid_j_vy_max )
then
1060 sll_allocate( new_int_list_element, ierr )
1061 new_int_list_element%value = node_index
1062 head => nodes_in_flow_cell(j_x,j_y,j_vx,j_vy)%pointed_element
1082 flow_grid_j_x_min = max(flow_grid_j_x_min, j_tmp)
1084 flow_grid_j_x_max = min(flow_grid_j_x_max, j_tmp)
1087 flow_grid_j_y_min = max(flow_grid_j_y_min, j_tmp)
1089 flow_grid_j_y_max = min(flow_grid_j_y_max, j_tmp)
1092 flow_grid_j_vx_min = max(flow_grid_j_vx_min, j_tmp)
1094 flow_grid_j_vx_max = min(flow_grid_j_vx_max, j_tmp)
1097 flow_grid_j_vy_min = max(flow_grid_j_vy_min, j_tmp)
1099 flow_grid_j_vy_max = min(flow_grid_j_vy_max, j_tmp)
1101 g_num_points_x = g%num_cells1
1102 if( reconstruct_f_on_last_node(1) ) g_num_points_x = g_num_points_x + 1
1103 sll_assert(
size(given_array_4d, 1) == g_num_points_x )
1105 g_num_points_y = g%num_cells2
1106 if( reconstruct_f_on_last_node(2) ) g_num_points_y = g_num_points_y + 1
1107 sll_assert(
size(given_array_4d, 2) == g_num_points_y )
1109 g_num_points_vx = g%num_cells3
1110 if( reconstruct_f_on_last_node(3) ) g_num_points_vx = g_num_points_vx + 1
1111 sll_assert(
size(given_array_4d, 3) == g_num_points_vx )
1113 g_num_points_vy = g%num_cells4
1114 if( reconstruct_f_on_last_node(4) ) g_num_points_vy = g_num_points_vy + 1
1115 sll_assert(
size(given_array_4d, 4) == g_num_points_vy )
1116 given_array_4d(:,:,:,:) = 0.0_f64
1118 h_g_grid_x = g%delta_eta1
1119 h_g_grid_y = g%delta_eta2
1120 h_g_grid_vx = g%delta_eta3
1121 h_g_grid_vy = g%delta_eta4
1123 g_grid_x_min = g%eta1_min
1124 g_grid_y_min = g%eta2_min
1125 g_grid_vx_min = g%eta3_min
1126 g_grid_vy_min = g%eta4_min
1134 sll_allocate(closest_particle(flow_grid_num_cells_x,flow_grid_num_cells_y,flow_grid_num_cells_vx,flow_grid_num_cells_vy),ierr)
1135 closest_particle(:,:,:,:) = 0
1137 allocate(closest_particle_distance(flow_grid_num_cells_x, &
1138 flow_grid_num_cells_y, &
1139 flow_grid_num_cells_vx, &
1140 flow_grid_num_cells_vy) , stat=ierr)
1141 call sll_s_test_error_code(ierr,
'Memory allocation Failure.', __file__, __line__)
1142 closest_particle_distance(:,:,:,:) = 0.0_f64
1144 closest_particle_distance_to_first_corner = 1d30
1145 k_particle_closest_to_first_corner = 0
1147 do k=1, self%n_particles
1150 coords = self%get_x(k)
1153 coords = self%get_v(k)
1164 if( j_x >= flow_grid_j_x_min .and. j_x <= flow_grid_j_x_max .and. &
1165 j_y >= flow_grid_j_y_min .and. j_y <= flow_grid_j_y_max .and. &
1166 j_vx >= flow_grid_j_vx_min .and. j_vx <= flow_grid_j_vx_max .and. &
1167 j_vy >= flow_grid_j_vy_min .and. j_vy <= flow_grid_j_vy_max )
then
1171 x_k - flow_grid_x_min, &
1172 y_k - flow_grid_y_min, &
1173 vx_k - flow_grid_vx_min, &
1174 vy_k - flow_grid_vy_min, &
1175 j_x, j_y, j_vx, j_vy, &
1181 closest_particle_distance &
1185 particle_distance_to_first_corner = abs(x_k - flow_grid_x_min ) &
1186 + abs(y_k - flow_grid_y_min ) &
1187 + abs(vx_k - flow_grid_vx_min) &
1188 + abs(vy_k - flow_grid_vy_min)
1189 if( particle_distance_to_first_corner < closest_particle_distance_to_first_corner )
then
1190 closest_particle_distance_to_first_corner = particle_distance_to_first_corner
1191 k_particle_closest_to_first_corner = k
1195 closest_particle(1,1,1,1) = k_particle_closest_to_first_corner
1197 if( .not. ( self%domain_is_periodic(1) .and. self%domain_is_periodic(2) ) )
then
1198 print*,
"WARNING -- STOP -- verify that the non-periodic case is well implemented"
1209 if(self%domain_is_periodic(1))
then
1211 mesh_period_x = self%lbf_grid%eta1_max - self%lbf_grid%eta1_min
1213 mesh_period_x = 0.0_f64
1216 if(self%domain_is_periodic(2))
then
1218 mesh_period_y = self%lbf_grid%eta2_max - self%lbf_grid%eta2_min
1220 mesh_period_y = 0.0_f64
1223 do j_x = flow_grid_j_x_min, flow_grid_j_x_max
1224 do j_y = flow_grid_j_y_min, flow_grid_j_y_max
1225 do j_vx = flow_grid_j_vx_min, flow_grid_j_vx_max
1226 do j_vy = flow_grid_j_vy_min, flow_grid_j_vy_max
1229 k = closest_particle(j_x,j_y,j_vx,j_vy)
1233 update_closest_particle_arrays_using_neighbor_cells(-1,0,0,0)
1235 if( j_x < flow_grid_num_cells_x )
then
1236 update_closest_particle_arrays_using_neighbor_cells( 1,0,0,0)
1240 update_closest_particle_arrays_using_neighbor_cells(0,-1,0,0)
1242 if( j_y < flow_grid_num_cells_y )
then
1243 update_closest_particle_arrays_using_neighbor_cells(0, 1,0,0)
1247 update_closest_particle_arrays_using_neighbor_cells(0,0,-1,0)
1249 if( j_vx < flow_grid_num_cells_vx )
then
1250 update_closest_particle_arrays_using_neighbor_cells(0,0, 1,0)
1254 update_closest_particle_arrays_using_neighbor_cells(0,0,0,-1)
1256 if( j_vy < flow_grid_num_cells_vy )
then
1257 update_closest_particle_arrays_using_neighbor_cells(0,0,0, 1)
1261 k = closest_particle(j_x,j_y,j_vx,j_vy)
1268 call self%get_ltp_deformation_matrix ( &
1276 x_k,y_k,vx_k,vy_k, &
1285 m_x,m_y,m_vx,m_vy, &
1287 self%n_particles_x, self%n_particles_y, &
1288 self%n_particles_vx, self%n_particles_vy &
1291 x_k_t0 = flow_grid_x_min + (m_x-0.5) * h_flow_grid_x
1292 y_k_t0 = flow_grid_y_min + (m_y-0.5) * h_flow_grid_y
1293 vx_k_t0 = flow_grid_vx_min + (m_vx-0.5) * h_flow_grid_vx
1294 vy_k_t0 = flow_grid_vy_min + (m_vy-0.5) * h_flow_grid_vy
1303 new_int_list_element => nodes_in_flow_cell(j_x,j_y,j_vx,j_vy)%pointed_element
1305 do while(
associated(new_int_list_element) )
1306 node_index = new_int_list_element%value
1308 x = self%sparse_grid_interpolator%hierarchy(node_index)%coordinate(1)
1309 y = self%sparse_grid_interpolator%hierarchy(node_index)%coordinate(2)
1310 vx = self%sparse_grid_interpolator%hierarchy(node_index)%coordinate(3)
1311 vy = self%sparse_grid_interpolator%hierarchy(node_index)%coordinate(4)
1316 vx_to_vxk = vx - vx_k
1317 vy_to_vyk = vy - vy_k
1320 x_t0_to_xk_t0 = d11 * x_to_xk + d12 * y_to_yk + d13 * vx_to_vxk + d14 * vy_to_vyk
1321 y_t0_to_yk_t0 = d21 * x_to_xk + d22 * y_to_yk + d23 * vx_to_vxk + d24 * vy_to_vyk
1322 vx_t0_to_vxk_t0 = d31 * x_to_xk + d32 * y_to_yk + d33 * vx_to_vxk + d34 * vy_to_vyk
1323 vy_t0_to_vyk_t0 = d41 * x_to_xk + d42 * y_to_yk + d43 * vx_to_vxk + d44 * vy_to_vyk
1325 x_t0 = x_t0_to_xk_t0 + x_k_t0
1326 y_t0 = y_t0_to_yk_t0 + y_k_t0
1327 vx_t0 = vx_t0_to_vxk_t0 + vx_k_t0
1328 vy_t0 = vy_t0_to_vyk_t0 + vy_k_t0
1340 reconstructed_f_value = self%interpolate_value_of_remapped_f(eta)
1341 self%tmp_f_values_on_remapping_sparse_grid(node_index) = reconstructed_f_value
1343 new_int_list_element => new_int_list_element%next
1362 i_min_x = int(ceiling( (flow_grid_x_min - g_grid_x_min + (j_x-1) * h_flow_grid_x) / h_g_grid_x + 1 ))
1363 i_min_y = int(ceiling( (flow_grid_y_min - g_grid_y_min + (j_y-1) * h_flow_grid_y) / h_g_grid_y + 1 ))
1364 i_min_vx = int(ceiling( (flow_grid_vx_min - g_grid_vx_min + (j_vx-1) * h_flow_grid_vx)/ h_g_grid_vx + 1 ))
1365 i_min_vy = int(ceiling( (flow_grid_vy_min - g_grid_vy_min + (j_vy-1) * h_flow_grid_vy)/ h_g_grid_vy + 1 ))
1367 i_max_x = int(ceiling( (flow_grid_x_min - g_grid_x_min + (j_x) * h_flow_grid_x) / h_g_grid_x + 1 )) - 1
1368 i_max_y = int(ceiling( (flow_grid_y_min - g_grid_y_min + (j_y) * h_flow_grid_y) / h_g_grid_y + 1 )) - 1
1369 i_max_vx = int(ceiling( (flow_grid_vx_min - g_grid_vx_min + (j_vx) * h_flow_grid_vx)/ h_g_grid_vx + 1 )) - 1
1370 i_max_vy = int(ceiling( (flow_grid_vy_min - g_grid_vy_min + (j_vy) * h_flow_grid_vy)/ h_g_grid_vy + 1 )) - 1
1372 i_min_x = max(i_min_x, 1)
1373 i_min_y = max(i_min_y, 1)
1374 i_min_vx = max(i_min_vx, 1)
1375 i_min_vy = max(i_min_vy, 1)
1377 i_max_x = min(i_max_x, g_num_points_x)
1378 i_max_y = min(i_max_y, g_num_points_y)
1379 i_max_vx = min(i_max_vx, g_num_points_vx)
1380 i_max_vy = min(i_max_vy, g_num_points_vy)
1382 do i_x = i_min_x, i_max_x
1383 x = g_grid_x_min + (i_x-1)*h_g_grid_x
1385 d1_x = d11 * x_to_xk
1386 d2_x = d21 * x_to_xk
1387 d3_x = d31 * x_to_xk
1388 d4_x = d41 * x_to_xk
1390 do i_y = i_min_y, i_max_y
1391 y = g_grid_y_min + (i_y-1)*h_g_grid_y
1393 d1_y = d12 * y_to_yk
1394 d2_y = d22 * y_to_yk
1395 d3_y = d32 * y_to_yk
1396 d4_y = d42 * y_to_yk
1398 do i_vx = i_min_vx, i_max_vx
1399 vx = g_grid_vx_min + (i_vx-1)*h_g_grid_vx
1400 vx_to_vxk = vx - vx_k
1401 d1_vx = d13 * vx_to_vxk
1402 d2_vx = d23 * vx_to_vxk
1403 d3_vx = d33 * vx_to_vxk
1404 d4_vx = d43 * vx_to_vxk
1407 do i_vy = i_min_vy, i_max_vy
1408 vy = g_grid_vy_min + (i_vy-1)*h_g_grid_vy
1409 vy_to_vyk = vy - vy_k
1410 d1_vy = d14 * vy_to_vyk
1411 d2_vy = d24 * vy_to_vyk
1412 d3_vy = d34 * vy_to_vyk
1413 d4_vy = d44 * vy_to_vyk
1418 x_t0_to_xk_t0 = d1_x + d1_y + d1_vx + d1_vy
1419 y_t0_to_yk_t0 = d2_x + d2_y + d2_vx + d2_vy
1420 vx_t0_to_vxk_t0 = d3_x + d3_y + d3_vx + d3_vy
1421 vy_t0_to_vyk_t0 = d4_x + d4_y + d4_vx + d4_vy
1423 x_t0 = x_t0_to_xk_t0 + x_k_t0
1424 y_t0 = y_t0_to_yk_t0 + y_k_t0
1425 vx_t0 = vx_t0_to_vxk_t0 + vx_k_t0
1426 vy_t0 = vy_t0_to_vyk_t0 + vy_k_t0
1438 reconstructed_f_value = self%interpolate_value_of_remapped_f(eta)
1443 print*,
"[WRITE ON GIVEN GRID] reconstructing "
1444 print*,
"on: eta = ", eta
1445 print*,
"value: reconstructed_f_value = ", reconstructed_f_value
1451 if( reconstructed_f_value /= 0 )
then
1453 sll_assert( 1 <= i_x .and. i_x <= g_num_points_x )
1454 sll_assert( 1 <= i_y .and. i_y <= g_num_points_y )
1455 sll_assert( 1 <= i_vx .and. i_vx <= g_num_points_vx )
1456 sll_assert( 1 <= i_vy .and. i_vy <= g_num_points_vy )
1458 if( abs(given_array_4d(i_x, i_y, i_vx, i_vy)) > 0.00001 )
then
1459 print *,
"Warning -- 987698666999979979 -- stored value should be zero"
1460 print *,
"given_array_4d(i_x, i_y, i_vx, i_vy) = ", given_array_4d(i_x, i_y, i_vx, i_vy)
1461 print *,
"with (i_x, i_y, i_vx, i_vy) = ", i_x, i_y, i_vx, i_vy
1463 given_array_4d(i_x, i_y, i_vx, i_vy) = reconstructed_f_value
1466 print *,
"Warning -- 654654535466545434564 -- just reconstructed a Zero value"
1480 if( enforce_total_charge )
then
1482 if( deposited_charge == 0 )
then
1483 print *,
"WARNING (76576537475) -- total deposited charge is zero, which is strange..."
1484 print *,
" -- (no charge correction in this case) "
1486 charge_correction_factor = target_total_charge / deposited_charge
1487 print *,
"[Enforcing charge]: target_total_charge, deposited_charge, charge_correction_factor = ", &
1488 target_total_charge, deposited_charge, charge_correction_factor
1489 do i_x = 1, g_num_points_x
1490 do i_y = 1, g_num_points_y
1491 do i_vx = 1, g_num_points_vx
1492 do i_vy = 1, g_num_points_vy
1493 given_array_4d(i_x, i_y, i_vx, i_vy) = given_array_4d(i_x, i_y, i_vx, i_vy) &
1494 * charge_correction_factor
1508 type(sll_t_cartesian_mesh_4d),
pointer :: void_grid_4d
1509 sll_real64,
dimension(:,:,:,:),
pointer :: void_array_4d
1510 logical :: dummy_reconstruct_f_on_last_node(4)
1511 sll_real64 :: dummy_target_total_charge
1512 logical :: dummy_enforce_total_charge
1514 nullify(void_grid_4d)
1515 nullify(void_array_4d)
1516 dummy_reconstruct_f_on_last_node = .false.
1517 dummy_target_total_charge = 0.0_f64
1518 dummy_enforce_total_charge = .false.
1520 call self%reconstruct_f_lbf( &
1524 dummy_reconstruct_f_on_last_node, &
1525 dummy_target_total_charge, &
1526 dummy_enforce_total_charge )
1537 reconstruct_f_on_last_node, &
1538 target_total_charge, &
1539 enforce_total_charge &
1542 type(sll_t_cartesian_mesh_4d),
pointer,
intent(in) :: given_grid_4d
1543 sll_real64,
dimension(:,:,:,:),
pointer,
intent(inout) :: given_array_4d
1544 logical,
intent(in) :: reconstruct_f_on_last_node(4)
1545 sll_real64,
intent(in) :: target_total_charge
1546 logical,
intent(in) :: enforce_total_charge
1548 call self%reconstruct_f_lbf( &
1552 reconstruct_f_on_last_node, &
1553 target_total_charge, &
1554 enforce_total_charge )
1604 sll_int32,
intent(in) :: k
1606 sll_real64,
intent(in) :: mesh_period_x
1607 sll_real64,
intent(in) :: mesh_period_y
1609 sll_real64,
intent(in) :: h_particles_x
1610 sll_real64,
intent(in) :: h_particles_y
1611 sll_real64,
intent(in) :: h_particles_vx
1612 sll_real64,
intent(in) :: h_particles_vy
1614 sll_real64,
intent(out) :: x_k, y_k
1615 sll_real64,
intent(out) :: vx_k, vy_k
1616 sll_real64,
intent(out) :: d11,d12,d13,d14
1617 sll_real64,
intent(out) :: d21,d22,d23,d24
1618 sll_real64,
intent(out) :: d31,d32,d33,d34
1619 sll_real64,
intent(out) :: d41,d42,d43,d44
1622 sll_real64 :: x_k_left, x_k_right
1623 sll_real64 :: y_k_left, y_k_right
1624 sll_real64 :: vx_k_left, vx_k_right
1625 sll_real64 :: vy_k_left, vy_k_right
1626 sll_real64,
dimension(3) :: coords
1628 sll_real64 :: j11,j12,j13,j14
1629 sll_real64 :: j21,j22,j23,j24
1630 sll_real64 :: j31,j32,j33,j34
1631 sll_real64 :: j41,j42,j43,j44
1632 sll_real64 :: factor, det_j, inv_det_j
1635 sll_int32,
parameter :: dim_x = 1
1636 sll_int32,
parameter :: dim_y = 2
1637 sll_int32,
parameter :: dim_vx = 3
1638 sll_int32,
parameter :: dim_vy = 4
1639 sll_int32,
parameter :: left_ngb = -1
1640 sll_int32,
parameter :: right_ngb = 1
1642 logical domain_is_x_periodic
1643 logical domain_is_y_periodic
1645 domain_is_x_periodic = self%domain_is_periodic(1)
1646 domain_is_y_periodic = self%domain_is_periodic(2)
1650 coords = self%get_x(k)
1654 coords = self%get_v(k)
1661 factor = 1./(2*h_particles_x)
1663 k_ngb = self%get_neighbor_index(k, dim_x, right_ngb)
1664 if( k_ngb == k )
then
1672 coords = self%get_x(k_ngb)
1673 x_k_right = coords(1)
1674 y_k_right = coords(2)
1675 coords = self%get_v(k_ngb)
1676 vx_k_right = coords(1)
1677 vy_k_right = coords(2)
1679 if( domain_is_x_periodic .and. x_k_right < x_k - 0.5*mesh_period_x ) x_k_right = x_k_right + mesh_period_x
1680 if( domain_is_x_periodic .and. x_k_right > x_k + 0.5*mesh_period_x ) x_k_right = x_k_right - mesh_period_x
1681 if( domain_is_y_periodic .and. y_k_right < y_k - 0.5*mesh_period_y ) y_k_right = y_k_right + mesh_period_y
1682 if( domain_is_y_periodic .and. y_k_right > y_k + 0.5*mesh_period_y ) y_k_right = y_k_right - mesh_period_y
1686 k_ngb = self%get_neighbor_index(k, dim_x, left_ngb)
1687 if( k_ngb == k )
then
1695 coords = self%get_x(k_ngb)
1696 x_k_left = coords(1)
1697 y_k_left = coords(2)
1698 coords = self%get_v(k_ngb)
1699 vx_k_left = coords(1)
1700 vy_k_left = coords(2)
1702 if( domain_is_x_periodic .and. x_k_left < x_k - 0.5*mesh_period_x ) x_k_left = x_k_left + mesh_period_x
1703 if( domain_is_x_periodic .and. x_k_left > x_k + 0.5*mesh_period_x ) x_k_left = x_k_left - mesh_period_x
1704 if( domain_is_y_periodic .and. y_k_left < y_k - 0.5*mesh_period_y ) y_k_left = y_k_left + mesh_period_y
1705 if( domain_is_y_periodic .and. y_k_left > y_k + 0.5*mesh_period_y ) y_k_left = y_k_left - mesh_period_y
1708 j11 = factor * ( x_k_right - x_k_left )
1709 j21 = factor * ( y_k_right - y_k_left )
1710 j31 = factor * ( vx_k_right - vx_k_left )
1711 j41 = factor * ( vy_k_right - vy_k_left )
1714 factor = 1./(2*h_particles_y)
1716 k_ngb = self%get_neighbor_index(k, dim_y, right_ngb)
1717 if( k_ngb == k )
then
1725 coords = self%get_x(k_ngb)
1726 x_k_right = coords(1)
1727 y_k_right = coords(2)
1728 coords = self%get_v(k_ngb)
1729 vx_k_right = coords(1)
1730 vy_k_right = coords(2)
1732 if( domain_is_x_periodic .and. x_k_right < x_k - 0.5*mesh_period_x ) x_k_right = x_k_right + mesh_period_x
1733 if( domain_is_x_periodic .and. x_k_right > x_k + 0.5*mesh_period_x ) x_k_right = x_k_right - mesh_period_x
1734 if( domain_is_y_periodic .and. y_k_right < y_k - 0.5*mesh_period_y ) y_k_right = y_k_right + mesh_period_y
1735 if( domain_is_y_periodic .and. y_k_right > y_k + 0.5*mesh_period_y ) y_k_right = y_k_right - mesh_period_y
1738 k_ngb = self%get_neighbor_index(k, dim_y, left_ngb)
1739 if( k_ngb == k )
then
1747 coords = self%get_x(k_ngb)
1748 x_k_left = coords(1)
1749 y_k_left = coords(2)
1750 coords = self%get_v(k_ngb)
1751 vx_k_left = coords(1)
1752 vy_k_left = coords(2)
1754 if( domain_is_x_periodic .and. x_k_left < x_k - 0.5*mesh_period_x ) x_k_left = x_k_left + mesh_period_x
1755 if( domain_is_x_periodic .and. x_k_left > x_k + 0.5*mesh_period_x ) x_k_left = x_k_left - mesh_period_x
1756 if( domain_is_y_periodic .and. y_k_left < y_k - 0.5*mesh_period_y ) y_k_left = y_k_left + mesh_period_y
1757 if( domain_is_y_periodic .and. y_k_left > y_k + 0.5*mesh_period_y ) y_k_left = y_k_left - mesh_period_y
1760 j12 = factor * ( x_k_right - x_k_left )
1761 j22 = factor * ( y_k_right - y_k_left )
1762 j32 = factor * ( vx_k_right - vx_k_left )
1763 j42 = factor * ( vy_k_right - vy_k_left )
1767 factor = 1./(2*h_particles_vx)
1769 k_ngb = self%get_neighbor_index(k, dim_vx, right_ngb)
1770 if( k_ngb == k )
then
1778 coords = self%get_x(k_ngb)
1779 x_k_right = coords(1)
1780 y_k_right = coords(2)
1781 coords = self%get_v(k_ngb)
1782 vx_k_right = coords(1)
1783 vy_k_right = coords(2)
1785 if( domain_is_x_periodic .and. x_k_right < x_k - 0.5*mesh_period_x ) x_k_right = x_k_right + mesh_period_x
1786 if( domain_is_x_periodic .and. x_k_right > x_k + 0.5*mesh_period_x ) x_k_right = x_k_right - mesh_period_x
1787 if( domain_is_y_periodic .and. y_k_right < y_k - 0.5*mesh_period_y ) y_k_right = y_k_right + mesh_period_y
1788 if( domain_is_y_periodic .and. y_k_right > y_k + 0.5*mesh_period_y ) y_k_right = y_k_right - mesh_period_y
1791 k_ngb = self%get_neighbor_index(k, dim_vx, left_ngb)
1792 if( k_ngb == k )
then
1800 coords = self%get_x(k_ngb)
1801 x_k_left = coords(1)
1802 y_k_left = coords(2)
1803 coords = self%get_v(k_ngb)
1804 vx_k_left = coords(1)
1805 vy_k_left = coords(2)
1807 if( domain_is_x_periodic .and. x_k_left < x_k - 0.5*mesh_period_x ) x_k_left = x_k_left + mesh_period_x
1808 if( domain_is_x_periodic .and. x_k_left > x_k + 0.5*mesh_period_x ) x_k_left = x_k_left - mesh_period_x
1809 if( domain_is_y_periodic .and. y_k_left < y_k - 0.5*mesh_period_y ) y_k_left = y_k_left + mesh_period_y
1810 if( domain_is_y_periodic .and. y_k_left > y_k + 0.5*mesh_period_y ) y_k_left = y_k_left - mesh_period_y
1813 j13 = factor * ( x_k_right - x_k_left )
1814 j23 = factor * ( y_k_right - y_k_left )
1815 j33 = factor * ( vx_k_right - vx_k_left )
1816 j43 = factor * ( vy_k_right - vy_k_left )
1820 factor = 1./(2*h_particles_vy)
1822 k_ngb = self%get_neighbor_index(k, dim_vy, right_ngb)
1823 if( k_ngb == k )
then
1831 coords = self%get_x(k_ngb)
1832 x_k_right = coords(1)
1833 y_k_right = coords(2)
1834 coords = self%get_v(k_ngb)
1835 vx_k_right = coords(1)
1836 vy_k_right = coords(2)
1838 if( domain_is_x_periodic .and. x_k_right < x_k - 0.5*mesh_period_x ) x_k_right = x_k_right + mesh_period_x
1839 if( domain_is_x_periodic .and. x_k_right > x_k + 0.5*mesh_period_x ) x_k_right = x_k_right - mesh_period_x
1840 if( domain_is_y_periodic .and. y_k_right < y_k - 0.5*mesh_period_y ) y_k_right = y_k_right + mesh_period_y
1841 if( domain_is_y_periodic .and. y_k_right > y_k + 0.5*mesh_period_y ) y_k_right = y_k_right - mesh_period_y
1844 k_ngb = self%get_neighbor_index(k, dim_vy, left_ngb)
1845 if( k_ngb == k )
then
1853 coords = self%get_x(k_ngb)
1854 x_k_left = coords(1)
1855 y_k_left = coords(2)
1856 coords = self%get_v(k_ngb)
1857 vx_k_left = coords(1)
1858 vy_k_left = coords(2)
1860 if( domain_is_x_periodic .and. x_k_left < x_k - 0.5*mesh_period_x ) x_k_left = x_k_left + mesh_period_x
1861 if( domain_is_x_periodic .and. x_k_left > x_k + 0.5*mesh_period_x ) x_k_left = x_k_left - mesh_period_x
1862 if( domain_is_y_periodic .and. y_k_left < y_k - 0.5*mesh_period_y ) y_k_left = y_k_left + mesh_period_y
1863 if( domain_is_y_periodic .and. y_k_left > y_k + 0.5*mesh_period_y ) y_k_left = y_k_left - mesh_period_y
1866 j14 = factor * ( x_k_right - x_k_left )
1867 j24 = factor * ( y_k_right - y_k_left )
1868 j34 = factor * ( vx_k_right - vx_k_left )
1869 j44 = factor * ( vy_k_right - vy_k_left )
1874 det_j = j11 * j22 * j33 * j44 &
1875 + j11 * j23 * j34 * j42 &
1876 + j11 * j24 * j32 * j43 &
1877 + j12 * j21 * j34 * j43 &
1878 + j12 * j23 * j31 * j44 &
1879 + j12 * j24 * j33 * j41 &
1880 + j13 * j21 * j32 * j44 &
1881 + j13 * j22 * j34 * j41 &
1882 + j13 * j24 * j31 * j42 &
1883 + j14 * j21 * j33 * j42 &
1884 + j14 * j22 * j31 * j43 &
1885 + j14 * j23 * j32 * j41 &
1886 - j11 * j22 * j34 * j43 &
1887 - j11 * j23 * j32 * j44 &
1888 - j11 * j24 * j33 * j42 &
1889 - j12 * j21 * j33 * j44 &
1890 - j12 * j23 * j34 * j41 &
1891 - j12 * j24 * j31 * j43 &
1892 - j13 * j21 * j34 * j42 &
1893 - j13 * j22 * j31 * j44 &
1894 - j13 * j24 * j32 * j41 &
1895 - j14 * j21 * j32 * j43 &
1896 - j14 * j22 * j33 * j41 &
1897 - j14 * j23 * j31 * j42
1899 inv_det_j = 1./det_j
1901 d11 = j22 * j33 * j44 &
1907 d11 = inv_det_j * d11
1909 d12 = j12 * j34 * j43 &
1915 d12 = inv_det_j * d12
1917 d13 = j12 * j23 * j44 &
1923 d13 = inv_det_j * d13
1925 d14 = j12 * j24 * j33 &
1931 d14 = inv_det_j * d14
1933 d21 = j21 * j34 * j43 &
1939 d21 = inv_det_j * d21
1941 d22 = j11 * j33 * j44 &
1947 d22 = inv_det_j * d22
1949 d23 = j11 * j24 * j43 &
1955 d23 = inv_det_j * d23
1957 d24 = j11 * j23 * j34 &
1963 d24 = inv_det_j * d24
1965 d31 = j21 * j32 * j44 &
1971 d31 = inv_det_j * d31
1973 d32 = j11 * j34 * j42 &
1979 d32 = inv_det_j * d32
1981 d33 = j11 * j22 * j44 &
1987 d33 = inv_det_j * d33
1989 d34 = j11 * j24 * j32 &
1995 d34 = inv_det_j * d34
1997 d41 = j21 * j33 * j42 &
2003 d41 = inv_det_j * d41
2005 d42 = j11 * j32 * j43 &
2011 d42 = inv_det_j * d42
2013 d43 = j11 * j23 * j42 &
2019 d43 = inv_det_j * d43
2021 d44 = j11 * j22 * j33 &
2027 d44 = inv_det_j * d44
2035 sll_real64,
intent(inout) :: x
2036 sll_real64,
intent(inout) :: y
2037 sll_real64 :: eta_max, eta_min
2039 if( p_group%domain_is_periodic(1) )
then
2040 eta_min = p_group%lbf_grid%eta1_min
2041 eta_max = p_group%lbf_grid%eta1_max
2042 if( (x < eta_min) .or. (x >= eta_max) ) x = eta_min + modulo(x - eta_min, eta_max - eta_min)
2045 if( p_group%domain_is_periodic(2) )
then
2046 eta_min = p_group%lbf_grid%eta2_min
2047 eta_max = p_group%lbf_grid%eta2_max
2048 if( (y < eta_min) .or. (y >= eta_max) ) y = eta_min + modulo(y - eta_min, eta_max - eta_min)
2057 new_element%next => head
2058 new_list => new_element
2066 j_x, j_y, j_vx, j_vy, &
2067 n_parts_x, n_parts_y, n_parts_vx, n_parts_vy &
2069 sll_int32,
intent(out):: k
2070 sll_int32,
intent(in) :: j_x
2071 sll_int32,
intent(in) :: j_y
2072 sll_int32,
intent(in) :: j_vx
2073 sll_int32,
intent(in) :: j_vy
2074 sll_int32,
intent(in) :: n_parts_x
2075 sll_int32,
intent(in) :: n_parts_y
2076 sll_int32,
intent(in) :: n_parts_vx
2077 sll_int32,
intent(in) :: n_parts_vy
2079 if( j_x <= 0 .or. j_x > n_parts_x &
2080 .or. j_y <= 0 .or. j_y > n_parts_y &
2081 .or. j_vx <= 0 .or. j_vx > n_parts_vx &
2082 .or. j_vy <= 0 .or. j_vy > n_parts_vy )
then
2085 k = 1+ (j_vy-1) + (j_vx-1) * n_parts_vy + (j_y-1) * n_parts_vy * n_parts_vx + (j_x-1) * n_parts_vy * n_parts_vx * n_parts_y
2088 sll_assert( k <= n_parts_x * n_parts_y * n_parts_vx * n_parts_vy )
2095 j_x, j_y, j_vx, j_vy, &
2097 n_parts_x, n_parts_y, n_parts_vx, n_parts_vy &
2099 sll_int32,
intent(out) :: j_x
2100 sll_int32,
intent(out) :: j_y
2101 sll_int32,
intent(out) :: j_vx
2102 sll_int32,
intent(out) :: j_vy
2103 sll_int32,
intent(in) :: k
2104 sll_int32,
intent(in) :: n_parts_x
2105 sll_int32,
intent(in) :: n_parts_y
2106 sll_int32,
intent(in) :: n_parts_vx
2107 sll_int32,
intent(in) :: n_parts_vy
2112 j_vy = mod(k_aux, n_parts_vy) + 1
2114 k_aux = (k_aux - (j_vy-1)) / n_parts_vy
2116 j_vx = mod(k_aux, n_parts_vx) + 1
2118 k_aux = (k_aux - (j_vx-1)) / n_parts_vx
2120 j_y = mod(k_aux, n_parts_y) + 1
2122 k_aux = (k_aux - (j_y-1)) / n_parts_y
2126 sll_assert(j_x <= n_parts_x)
2134 sll_int32,
intent(out) :: j
2135 sll_real64,
intent(in) :: x
2136 sll_real64,
intent(in) :: x_min
2137 sll_real64,
intent(in) :: h
2139 j = int( (x - x_min) / h ) + 1
2146 x_aux, y_aux, vx_aux, vy_aux, &
2148 h_cell_x, h_cell_y, h_cell_vx, h_cell_vy, &
2150 closest_particle_distance)
2152 sll_int32,
intent(in) :: k_part
2153 sll_int32,
intent(in) :: i, j, l, m
2154 sll_real64,
intent(in) :: x_aux
2155 sll_real64,
intent(in) :: y_aux
2156 sll_real64,
intent(in) :: vx_aux
2157 sll_real64,
intent(in) :: vy_aux
2158 sll_real64,
intent(in) :: h_cell_x, h_cell_y, h_cell_vx, h_cell_vy
2159 sll_int32,
dimension(:,:,:,:),
intent(inout) :: closest_particle
2160 sll_real64,
dimension(:,:,:,:),
intent(inout) :: closest_particle_distance
2161 sll_real64 :: square_dist_to_cell_center
2163 square_dist_to_cell_center = (x_aux - (i + 0.5) * h_cell_x )**2. &
2164 + (y_aux - (j + 0.5) * h_cell_y )**2. &
2165 + (vx_aux - (l + 0.5) * h_cell_vx )**2. &
2166 + (vy_aux - (m + 0.5) * h_cell_vy )**2.
2169 if(closest_particle(i,j,l,m) == 0 .or. square_dist_to_cell_center < closest_particle_distance(i,j,l,m))
then
2170 closest_particle(i,j,l,m) = k_part
2171 closest_particle_distance(i,j,l,m) = square_dist_to_cell_center
Cartesian mesh basic types.
type(sll_t_cartesian_mesh_4d) function, pointer, public sll_f_new_cartesian_mesh_4d(num_cells1, num_cells2, num_cells3, num_cells4, eta1_min, eta1_max, eta2_min, eta2_max, eta3_min, eta3_max, eta4_min, eta4_max)
allocates the memory space for a new 4D cartesian mesh on the heap,
Fortran module where set some physical and mathematical constants.
real(kind=f64), parameter, public sll_p_pi
Parameters to define common initial distributions.
Module for a particle group with linearized-backward-flow (lbf) resamplings.
subroutine set_v_2d2v_lbf(self, i, x)
Set the velocity of a particle.
subroutine reset_particles_weights_with_direct_interpolation(self, target_total_charge, enforce_total_charge)
reset_particles_weights_with_direct_interpolation ---------------------------------------------------...
subroutine sample(self, target_total_charge, enforce_total_charge, init_f_params, rand_seed, rank, world_size)
sample (layer for resample procedure) ---------------------------------------------------------------...
pure real(kind=f64) function, dimension(3) get_x_2d2v_lbf(self, i)
Getters ---------------------------------------------------------------------------------------------...
subroutine reset_particles_positions(self)
reset_particles_positions ---------------------------------------------------------------------------...
integer(kind=i32) function get_neighbor_index(self, k, dim, dir)
get_neighbor_index ----------------------------------------------------------------------------------...
subroutine delete_particle_group_2d2v_lbf(self)
Destructor ------------------------------------------------------------------------------------------...
subroutine write_known_density_on_remapping_grid(self, distribution_params)
write_known_density_on_remapping_grid ---------------------------------------------------------------...
subroutine set_x_2d2v_lbf(self, i, x)
Setters ---------------------------------------------------------------------------------------------...
subroutine get_1d_cell_containing_point(j, x, x_min, h)
get_1d_cell_containing_point ------------------------------------------------------------------------...
subroutine get_ltp_deformation_matrix(self, k, mesh_period_x, mesh_period_y, h_particles_x, h_particles_y, h_particles_vx, h_particles_vy, x_k, y_k, vx_k, vy_k, d11, d12, d13, d14, d21, d22, d23, d24, d31, d32, d33, d34, d41, d42, d43, d44)
get_ltp_deformation_matrix --------------------------------------------------------------------------...
integer(kind=i32), parameter sll_p_lbf_given_grid
subroutine convert_4d_index_to_1d(k, j_x, j_y, j_vx, j_vy, n_parts_x, n_parts_y, n_parts_vx, n_parts_vy)
convert_4d_index_to_1d ------------------------------------------------------------------------------...
subroutine update_closest_particle_arrays(k_part, x_aux, y_aux, vx_aux, vy_aux, i, j, l, m, h_cell_x, h_cell_y, h_cell_vx, h_cell_vy, closest_particle, closest_particle_distance)
update_closest_particle_arrays ----------------------------------------------------------------------...
subroutine reconstruct_f_lbf(self, reconstruction_set_type, given_grid_4d, given_array_4d, reconstruct_f_on_last_node, target_total_charge, enforce_total_charge)
macro for the lbf approximation of a transported density (reconstruct_f_lbf) below ------------------...
pure real(kind=f64) function get_common_weight_2d2v_lbf(self)
Set the common weight.
pure real(kind=f64) function, dimension(self%n_weights) get_weights_2d2v_lbf(self, i)
Get weights of a particle.
subroutine initialize_particle_group_2d2v_lbf(self, species_charge, species_mass, domain_is_x_periodic, domain_is_y_periodic, remap_degree, remapping_grid_eta_min, remapping_grid_eta_max, remapping_sparse_grid_max_levels, n_particles_x, n_particles_y, n_particles_vx, n_particles_vy, n_weights)
Initializer -----------------------------------------------------------------------------------------...
subroutine, public sll_s_new_particle_group_2d2v_lbf_ptr(particle_group, species_charge, species_mass, domain_is_x_periodic, domain_is_y_periodic, remap_degree, remapping_grid_eta_min, remapping_grid_eta_max, remapping_sparse_grid_max_levels, n_particles_x, n_particles_y, n_particles_vx, n_particles_vy)
Constructor for abstract type.
integer(kind=i32), parameter sll_p_lbf_remapping_grid
possible values for the parameter reconstruction_set_type in the reconstruction routine
subroutine convert_1d_index_to_4d(j_x, j_y, j_vx, j_vy, k, n_parts_x, n_parts_y, n_parts_vx, n_parts_vy)
convert_1d_index_to_4d ------------------------------------------------------------------------------...
subroutine resample(self, target_total_charge, enforce_total_charge, init_f_params, rand_seed, rank, world_size)
resample (and sample) -------------------------------------------------------------------------------...
subroutine set_weights_2d2v_lbf(self, i, x)
Set the weights of a particle.
pure real(kind=f64) function get_mass_2d2v_lbf(self, i, i_weight)
Get mass of a particle ( m * particle_weight)
subroutine reconstruct_f_lbf_on_given_grid(self, given_grid_4d, given_array_4d, reconstruct_f_on_last_node, target_total_charge, enforce_total_charge)
reconstruct_f_lbf_on_remapping_grid -----------------------------------------------------------------...
pure real(kind=f64) function get_charge_2d2v_lbf(self, i, i_weight)
Get charge of a particle (q * particle_weight)
subroutine reconstruct_f_lbf_on_remapping_grid(self)
reconstruct_f_lbf_on_remapping_grid -----------------------------------------------------------------...
pure real(kind=f64) function, dimension(3) get_v_2d2v_lbf(self, i)
Get the velocity of a particle.
real(kind=f64) function interpolate_value_of_remapped_f(self, eta)
interpolate_value_of_remapped_f ---------------------------------------------------------------------...
subroutine set_common_weight_2d2v_lbf(self, x)
Set the common weight.
subroutine periodic_correction(p_group, x, y)
periodic_correction ---------------------------------------------------------------------------------...
type(sll_t_int_list_element) function, pointer sll_f_add_element_in_int_list(head, new_element)
sll_f_add_element_in_int_list -----------------------------------------------------------------------...
Implementation of a 4D sparse grid with interpolation routines.
Abstract data type for parameters of initial distribution.
a pointer type is needed for arrays of lists
linked lists of integers, used in some of the module routines
Group of sll_t_particle_group_2d2v_lbf.
Sparse grid object for 4d with interpolation routines. Note in 4d we have only an implementation of a...