7 #include "sll_assert.h" 
    8 #include "sll_errors.h" 
    9 #include "sll_memory.h" 
   10 #include "sll_working_precision.h" 
   91      sll_int32 :: spline_degree 
 
   98      sll_real64, 
pointer     :: efield_dofs(:,:) 
 
   99      sll_real64, 
pointer     :: bfield_dofs(:)   
 
  100      sll_real64, 
allocatable :: j_dofs(:,:)      
 
  101      sll_real64, 
allocatable :: j_dofs_local(:,:)
 
  102      sll_real64, 
allocatable :: particle_mass_0_local(:,:) 
 
  103      sll_real64, 
allocatable :: particle_mass_1_local(:,:) 
 
  105      sll_int32 :: n_particles_max 
 
  106      sll_real64, 
allocatable :: xnew(:,:) 
 
  107      sll_real64, 
allocatable :: vnew(:,:,:) 
 
  108      sll_real64, 
allocatable :: efield_dofs_new(:,:) 
 
  109      sll_real64, 
allocatable :: efield_dofs_work(:,:) 
 
  111      sll_int32  :: boundary_particles = 100 
 
  112      sll_int32 :: counter_left = 0 
 
  113      sll_int32 :: counter_right = 0 
 
  114      logical :: boundary = .false. 
 
  115      sll_real64, 
pointer     :: rhob(:) => null() 
 
  116      sll_real64 :: force_sign = 1._f64 
 
  117      logical    :: jmean = .false. 
 
  119      sll_real64 :: solver_tolerance = 1d-12 
 
  122      sll_int32 :: max_iter = 10 
 
  123      sll_real64 :: iter_tolerance = 1d-10 
 
  125      sll_int32 :: n_failed = 0 
 
  126      sll_int32 :: iter_counter = 0 
 
  127      sll_int32 :: niter(100000) 
 
  150     sll_real64,                                           
intent( in    ) :: dt   
 
  152     sll_int32 :: i_part, i_sp, i
 
  153     sll_real64 :: xi(3), xnew(3), vi(3), vt, matrix(3,3), xs
 
  156     do i_sp=1,self%particle_group%n_species
 
  157        do i_part=1,self%particle_group%group(i_sp)%n_particles  
 
  159           xi = self%particle_group%group(i_sp)%get_x(i_part)
 
  160           vi = self%particle_group%group(i_sp)%get_v(i_part)
 
  162           matrix=self%map%jacobian_matrix_inverse( [xi(1), 0._f64, 0._f64] )
 
  164           vt = matrix(1,1) * vi(1)  
 
  171           do while(i < self%max_iter .and. err > self%iter_tolerance)
 
  173              matrix=self%map%jacobian_matrix_inverse( [xs, 0._f64, 0._f64] )
 
  174              xs = xi(1) + 0.5_f64 * dt * (vt + matrix(1,1) * vi(1) )
 
  175              err = abs(xs - xnew(1))
 
  181           call self%particle_group%group(i_sp)%set_x ( i_part, xnew )
 
  182           call self%particle_group%group(i_sp)%set_v ( i_part, vi )
 
  192     sll_real64,                                     
intent( inout ) :: xold
 
  193     sll_real64,                                     
intent( inout ) :: xnew
 
  194     sll_real64,                                     
intent( inout ) :: vi
 
  196     sll_real64 :: xmid, xbar, dx
 
  198     if(xnew < -1._f64 .or. xnew > 2._f64)
then 
  200        sll_error(
"particle boundary", 
"particle out of bound")
 
  201     else if(xnew < 0._f64 .or. xnew > 1._f64 )
then 
  202        if(xnew < 0._f64  )
then 
  204           self%counter_left = self%counter_left+1
 
  205        else if(xnew > 1._f64)
then 
  207           self%counter_right = self%counter_right+1
 
  209        dx = (xbar- xold)/(xnew-xold)
 
  210        xmid = xold + dx * (xnew-xold)
 
  213        select case(self%boundary_particles)
 
  216           xnew = 2._f64*xbar-xnew
 
  219           xnew = modulo(xnew, 1._f64)
 
  221           xnew = modulo(xnew, 1._f64)
 
  233     sll_real64,                                           
intent( in    ) :: dt   
 
  235     sll_int32  :: i_part, i_sp
 
  237     sll_real64 :: vi(3), vnew(3), xi(3), factor(3,3)
 
  238     sll_real64 :: bfield, cs, sn
 
  240     do i_sp=1,self%particle_group%n_species
 
  241        qmdt = self%particle_group%group(i_sp)%species%q_over_m()*dt;
 
  243        do i_part = 1, self%particle_group%group(i_sp)%n_particles
 
  244           vi = self%particle_group%group(i_sp)%get_v(i_part)
 
  245           xi = self%particle_group%group(i_sp)%get_x(i_part)
 
  247           call self%kernel_smoother_1%evaluate(xi(1), self%bfield_dofs, bfield)
 
  249           factor=self%map%jacobian_matrix( [xi(1), 0._f64, 0._f64])/self%map%jacobian( [xi(1), 0._f64, 0._f64])*qmdt
 
  251           cs = cos(factor(3,3)*bfield)
 
  252           sn = sin(factor(3,3)*bfield)
 
  254           vnew(1) = cs * vi(1) + sn * vi(2)
 
  255           vnew(2) = -sn* vi(1) + cs * vi(2)
 
  257           call self%particle_group%group(i_sp)%set_v( i_part, vnew )
 
  271     sll_real64,                                           
intent( in    ) :: dt   
 
  273     call self%maxwell_solver%compute_curl_part( dt, self%efield_dofs(:,2), self%bfield_dofs )
 
  286     sll_real64,                                           
intent( in    ) :: dt   
 
  288     sll_int32 :: i_part, i_sp, j
 
  289     sll_real64 :: vi(3), xi(3), wi(1)
 
  290     sll_real64 :: qoverm, jmat(3,3), metric, factor
 
  291     sll_real64 :: efield(2)
 
  292     sll_real64 :: rhs0(self%n_dofs0)
 
  293     sll_real64 :: rhs1(self%n_dofs1)
 
  296     self%j_dofs_local = 0.0_f64
 
  297     self%particle_mass_1_local = 0.0_f64
 
  298     self%particle_mass_0_local = 0.0_f64
 
  301     do i_sp = 1, self%particle_group%n_species
 
  302        qoverm = self%particle_group%group(i_sp)%species%q_over_m();
 
  303        factor = dt**2 * 0.25_f64* qoverm
 
  304        do i_part = 1, self%particle_group%group(i_sp)%n_particles
 
  305           vi = self%particle_group%group(i_sp)%get_v(i_part)
 
  306           xi = self%particle_group%group(i_sp)%get_x(i_part)
 
  309           wi = self%particle_group%group(i_sp)%get_charge(i_part)
 
  311           metric= self%map%metric_inverse_single( [xi(1), 0._f64, 0._f64], 1, 1 )
 
  312           jmat=self%map%jacobian_matrix_inverse( [xi(1), 0._f64, 0._f64] )
 
  315           call self%kernel_smoother_1%add_particle_mass_full( xi(1), wi(1) * metric * factor, &
 
  316                self%particle_mass_1_local )
 
  317           call self%kernel_smoother_0%add_particle_mass_full( xi(1), wi(1) * factor , &
 
  318                self%particle_mass_0_local )
 
  321           call self%kernel_smoother_1%add_charge( xi(1), wi(1)*jmat(1,1)*vi(1), &
 
  322                self%j_dofs_local(1:self%n_dofs1,1) )
 
  324           call self%kernel_smoother_0%add_charge( xi(1), wi(1)*vi(2), &
 
  325                self%j_dofs_local(:,2) )
 
  328           call self%kernel_smoother_1%evaluate &
 
  329                ( xi(1), self%efield_dofs(1:self%n_dofs1,1), efield(1) )
 
  330           call self%kernel_smoother_0%evaluate &
 
  331                ( xi(1), self%efield_dofs(:,2), efield(2))
 
  335              vi(j) = vi(j) + dt* 0.5_f64* qoverm *(jmat(1,j)* efield(1)+jmat(2,j)* efield(2))
 
  338           call self%particle_group%group(i_sp)%set_v( i_part, vi )
 
  342     self%j_dofs = 0.0_f64
 
  343     self%particle_mass_0%particle_mass = 0.0_f64
 
  344     self%particle_mass_1%particle_mass = 0.0_f64  
 
  348          self%n_dofs1, mpi_sum, self%j_dofs(1:self%n_dofs1,1) )
 
  350          self%n_dofs0, mpi_sum, self%j_dofs(:,2) )
 
  353          self%n_dofs1*(2*self%spline_degree-1), mpi_sum, self%particle_mass_1%particle_mass)
 
  355          self%n_dofs0*(2*self%spline_degree+1), mpi_sum, self%particle_mass_0%particle_mass)
 
  358     if ( self%jmean ) 
then 
  359        self%j_dofs(:,1) = self%j_dofs(:,1) - sum(self%j_dofs(:,1))/real(self%n_dofs1, f64)
 
  363     self%linear_operator_1%sign = -self%force_sign 
 
  364     call self%linear_operator_1%dot(self%efield_dofs(1:self%n_dofs1,1) , rhs1 )
 
  365     rhs1 = rhs1 - dt * self%force_sign * self%j_dofs(1:self%n_dofs1,1)
 
  367     self%linear_operator_1%sign = self%force_sign 
 
  368     call self%linear_solver_1%set_guess(self%efield_dofs(1:self%n_dofs1,1))
 
  369     call self%linear_solver_1%solve( rhs1 , self%efield_dofs(1:self%n_dofs1,1) )
 
  372     self%linear_operator_0%sign = -self%force_sign 
 
  373     call self%linear_operator_0%dot(self%efield_dofs(:,2) , rhs0 )
 
  374     rhs0 = rhs0 - self%force_sign * dt * self%j_dofs(:,2)
 
  377     self%linear_operator_0%sign = self%force_sign 
 
  378     call self%linear_solver_0%set_guess(self%efield_dofs(:,2))
 
  379     call self%linear_solver_0%solve( rhs0 , self%efield_dofs(:,2) )
 
  381     if( self%boundary ) then
 
  382        self%efield_dofs(1,2) = 0._f64
 
  383        self%efield_dofs(self%n_dofs0,2) = 0._f64
 
  387     do i_sp = 1, self%particle_group%n_species
 
  388        qoverm = self%particle_group%group(i_sp)%species%q_over_m();
 
  389        do i_part = 1, self%particle_group%group(i_sp)%n_particles
 
  390           vi = self%particle_group%group(i_sp)%get_v(i_part)
 
  391           xi = self%particle_group%group(i_sp)%get_x(i_part)
 
  394           call self%kernel_smoother_1%evaluate &
 
  395                ( xi(1), self%efield_dofs(1:self%n_dofs1,1), efield(1))
 
  396           call self%kernel_smoother_0%evaluate &
 
  397                ( xi(1), self%efield_dofs(:,2), efield(2))
 
  399           jmat = self%map%jacobian_matrix_inverse_transposed( [xi(1), 0._f64, 0._f64] )
 
  402              vi(j) = vi(j) + dt* 0.5_f64* qoverm *(jmat(j,1)*efield(1) + jmat(j,2)*efield(2))
 
  405           call self%particle_group%group(i_sp)%set_v( i_part, vi )
 
  419     sll_real64,                                           
intent( in    ) :: dt   
 
  421     sll_int32 :: i_part, i_sp, j
 
  422     sll_real64 :: vi(3), xi(3), wi(1), xnew(3), vbar(2)
 
  424     sll_real64 :: jmat(3,3), jmatrix(3,3), efield(2)
 
  426     sll_real64 :: residual(1), residual_local(1)
 
  427     sll_real64 :: xmid(1), xbar
 
  429     self%efield_dofs_new = self%efield_dofs
 
  430     do i_sp=1,self%particle_group%n_species
 
  431        do i_part = 1,self%particle_group%group(i_sp)%n_particles
 
  432           vi = self%particle_group%group(i_sp)%get_v(i_part)
 
  433           xnew = self%particle_group%group(i_sp)%get_x(i_part)
 
  434           self%vnew(i_sp,:, i_part) = vi(1:2)
 
  435           self%xnew(i_sp, i_part) = xnew(1)
 
  441     do while ( (residual(1) > self%iter_tolerance) .and. niter < self%max_iter )
 
  444        self%efield_dofs_work = 0.5_f64*( self%efield_dofs + self%efield_dofs_new )
 
  445        self%j_dofs_local = 0.0_f64
 
  448        do i_sp=1,self%particle_group%n_species
 
  449           qoverm = self%particle_group%group(i_sp)%species%q_over_m();
 
  450           do i_part = 1,self%particle_group%group(i_sp)%n_particles
 
  451              vi = self%particle_group%group(i_sp)%get_v(i_part)
 
  452              xi = self%particle_group%group(i_sp)%get_x(i_part)
 
  455              wi = self%particle_group%group(i_sp)%get_charge(i_part)
 
  457              vbar = 0.5_f64 * (self%vnew(i_sp,:, i_part)+vi(1:2))
 
  458              xnew(1) = self%xnew(i_sp, i_part)
 
  460              jmat = self%map%jacobian_matrix_inverse_transposed( [xi(1), 0._f64, 0._f64] )
 
  461              jmatrix=self%map%jacobian_matrix_inverse_transposed( [xnew(1), 0._f64, 0._f64] )
 
  462              vbar(1) = 0.5_f64 * (jmatrix(1,1)+jmat(1,1))*vbar(1) 
 
  463              xnew(1) = xi(1) + dt * vbar(1)
 
  465              if(xnew(1) < -1._f64 .or. xnew(1) > 2._f64)
then 
  467                 sll_error(
"particle boundary", 
"particle out of bound")
 
  468              else if(xnew(1) < 0._f64 .or. xnew(1) > 1._f64 )
then 
  469                 if(xnew(1) < 0._f64  )
then 
  471                 else if(xnew(1) > 1._f64)
then 
  476                 if ( abs(vbar(1)) > 1.0d-16 ) 
then 
  477                    call self%kernel_smoother_1%add_current_evaluate &
 
  478                         ( xi(1), xmid(1), wi(1), vbar(1), self%efield_dofs_work(1:self%n_dofs1,1), self%j_dofs_local(1:self%n_dofs1,1), &
 
  480                    call self%kernel_smoother_0%add_current_evaluate &
 
  481                         ( xi(1), xmid(1), wi(1)*vbar(2)/vbar(1), vbar(1), &
 
  482                         self%efield_dofs_work(:,2), self%j_dofs_local(:,2), &
 
  485                    call self%kernel_smoother_1%evaluate &
 
  486                         (xi(1), self%efield_dofs_work(1:self%n_dofs1,1), efield(1) )
 
  487                    efield(1) = efield(1)*dt
 
  488                    call self%kernel_smoother_0%add_charge( xi(1), &
 
  489                         wi(1)* vbar(2)*dt, self%j_dofs_local(:,2) )
 
  490                    call self%kernel_smoother_0%evaluate &
 
  491                         (xi(1), self%efield_dofs_work(:,2), efield(2) )
 
  492                    efield(2) = efield(2)*dt
 
  495                 jmatrix = self%map%jacobian_matrix_inverse_transposed( [xmid(1), 0._f64, 0._f64] )
 
  497                    vi(j) = vi(j) + qoverm *0.5_f64*((jmatrix(j,1)+jmat(j,1))*efield(1) + (jmatrix(j,2)+jmat(j,2))*efield(2))
 
  500                 select case(self%boundary_particles)
 
  502                    xnew = 2._f64*xbar-xnew
 
  506                    call self%kernel_smoother_0%add_charge(xmid, wi(1), self%rhob)
 
  508                    call self%kernel_smoother_0%add_charge(xmid, wi(1), self%rhob)
 
  509                    xnew = modulo(xnew, 1._f64)
 
  511                    call self%kernel_smoother_0%add_charge(xmid, -wi(1), self%rhob)
 
  513                    xnew = modulo(xnew, 1._f64)
 
  516                 if ( abs(vbar(1)) > 1.0d-16 ) 
then 
  517                    call self%kernel_smoother_1%add_current_evaluate &
 
  518                         ( xmid(1), xnew(1), wi(1), vbar(1), self%efield_dofs_work(1:self%n_dofs1,1), self%j_dofs_local(1:self%n_dofs1,1), &
 
  520                    call self%kernel_smoother_0%add_current_evaluate &
 
  521                         ( xmid(1), xnew(1), wi(1)*vbar(2)/vbar(1), vbar(1), &
 
  522                         self%efield_dofs_work(:,2), self%j_dofs_local(:,2), &
 
  524                    jmatrix = self%map%jacobian_matrix_inverse_transposed( [xnew(1), 0._f64, 0._f64] )
 
  526                       vi(j) = vi(j) + qoverm *0.5_f64*((jmatrix(j,1)+jmat(j,1))*efield(1) + (jmatrix(j,2)+jmat(j,2))*efield(2))
 
  533                 if ( abs(vbar(1)) > 1.0d-16 ) 
then 
  534                    call self%kernel_smoother_1%add_current_evaluate &
 
  535                         ( xi(1), xnew(1), wi(1), vbar(1), self%efield_dofs_work(1:self%n_dofs1,1), self%j_dofs_local(1:self%n_dofs1,1), &
 
  537                    call self%kernel_smoother_0%add_current_evaluate &
 
  538                         ( xi(1), xnew(1), wi(1)*vbar(2)/vbar(1), vbar(1), &
 
  539                         self%efield_dofs_work(:,2), self%j_dofs_local(:,2), &
 
  542                    call self%kernel_smoother_1%evaluate &
 
  543                         (xi(1), self%efield_dofs_work(1:self%n_dofs1,1), efield(1) )
 
  544                    efield(1) = efield(1)*dt
 
  545                    call self%kernel_smoother_0%add_charge( xi(1), &
 
  546                         wi(1)* vbar(2)*dt, self%j_dofs_local(:,2) )
 
  547                    call self%kernel_smoother_0%evaluate &
 
  548                         (xi(1), self%efield_dofs_work(:,2), efield(2) )
 
  549                    efield(2) = efield(2)*dt
 
  551                 jmatrix = self%map%jacobian_matrix_inverse_transposed( [xnew(1), 0._f64, 0._f64] )
 
  553                    vi(j) = vi(j) + qoverm *0.5_f64*((jmatrix(j,1)+jmat(j,1))*efield(1) + (jmatrix(j,2)+jmat(j,2))*efield(2))
 
  557              self%xnew(i_sp,i_part) = xnew(1)
 
  558              self%vnew(i_sp,:,i_part) = vi(1:2)
 
  562        self%j_dofs = 0.0_f64
 
  565             self%n_dofs1, mpi_sum, self%j_dofs(1:self%n_dofs1,1) )
 
  567             self%n_dofs0, mpi_sum, self%j_dofs(:,2) )
 
  569        self%efield_dofs_work = self%efield_dofs
 
  570        call self%maxwell_solver%compute_E_from_j(self%j_dofs(1:self%n_dofs1,1), 1, self%efield_dofs_work(1:self%n_dofs1,1) )
 
  571        call self%maxwell_solver%compute_E_from_j(self%j_dofs(:,2), 2, self%efield_dofs_work(:,2) )
 
  574        residual_local = (sum((self%efield_dofs_work-self%efield_dofs_new)**2))*self%maxwell_solver%delta_x
 
  576        residual = sqrt(residual)
 
  577        self%efield_dofs_new = self%efield_dofs_work
 
  580     if ( residual(1) > self%iter_tolerance ) 
then 
  581        print*, 
'Warning: Iteration no.', self%iter_counter+1 ,
'did not converge.', residual, niter
 
  582        self%n_failed = self%n_failed+1
 
  585     self%efield_dofs_work = 0.5_f64*( self%efield_dofs + self%efield_dofs_new )
 
  586     self%j_dofs_local = 0.0_f64
 
  589     do i_sp=1,self%particle_group%n_species
 
  590        qoverm = self%particle_group%group(i_sp)%species%q_over_m();
 
  591        do i_part = 1,self%particle_group%group(i_sp)%n_particles
 
  592           vi = self%particle_group%group(i_sp)%get_v(i_part)
 
  593           xi = self%particle_group%group(i_sp)%get_x(i_part)
 
  596           wi = self%particle_group%group(i_sp)%get_charge(i_part)
 
  598           vbar = 0.5_f64 * (self%vnew(i_sp,:, i_part)+vi(1:2))
 
  599           xnew(1) = self%xnew(i_sp, i_part)
 
  601           jmat = self%map%jacobian_matrix_inverse_transposed( [xi(1), 0._f64, 0._f64] )
 
  602           jmatrix=self%map%jacobian_matrix_inverse_transposed( [xnew(1), 0._f64, 0._f64] )
 
  603           vbar(1) = 0.5_f64 * (jmatrix(1,1)+jmat(1,1))*vbar(1) 
 
  604           xnew(1) = xi(1) + dt * vbar(1)
 
  607           call self%particle_group%group(i_sp)%set_x( i_part, xnew )
 
  608           call self%particle_group%group(i_sp)%set_v( i_part, vi )
 
  612     self%j_dofs = 0.0_f64
 
  615          self%n_dofs1, mpi_sum, self%j_dofs(1:self%n_dofs1,1) )
 
  617          self%n_dofs0, mpi_sum, self%j_dofs(:,2) )
 
  619     call self%maxwell_solver%compute_E_from_j(self%j_dofs(1:self%n_dofs1,1), 1, self%efield_dofs(1:self%n_dofs1,1) )
 
  620     call self%maxwell_solver%compute_E_from_j(self%j_dofs(:,2), 2, self%efield_dofs(:,2) )
 
  622     self%iter_counter = self%iter_counter + 1
 
  623     self%niter(self%iter_counter) = niter
 
  631     sll_real64,                                           
intent( in    ) :: xi(1)
 
  632     sll_real64,                                           
intent( inout ) :: xnew(1)
 
  633     sll_real64,                                           
intent( inout ) :: vi(2)
 
  634     sll_real64,                                           
intent( inout ) :: vbar(2)
 
  635     sll_real64,                                           
intent( in    ) :: wi(1)
 
  636     sll_real64,                                           
intent( in    ) :: qoverm
 
  637     sll_real64,                                           
intent( in    ) :: dt
 
  639     sll_real64 :: xmid(1), xbar
 
  640     sll_real64 :: jmatrix(3,3), jmat(3,3), efield(2)
 
  644     jmat = self%map%jacobian_matrix_inverse_transposed( [xi(1), 0._f64, 0._f64] )
 
  646     if(xnew(1) < -1._f64 .or. xnew(1) > 2._f64)
then 
  648        sll_error(
"particle boundary", 
"particle out of bound")
 
  649     else if(xnew(1) < 0._f64 .or. xnew(1) > 1._f64 )
then 
  650        if(xnew(1) < 0._f64  )
then 
  652           self%counter_left = self%counter_left+1
 
  653        else if(xnew(1) > 1._f64)
then 
  655           self%counter_right = self%counter_right+1
 
  659        if ( abs(vbar(1)) > 1.0d-16 ) 
then 
  660           call self%kernel_smoother_1%add_current_evaluate &
 
  661                ( xi(1), xmid(1), wi(1), vbar(1), self%efield_dofs_work(1:self%n_dofs1,1), self%j_dofs_local(1:self%n_dofs1,1), &
 
  663           call self%kernel_smoother_0%add_current_evaluate &
 
  664                ( xi(1), xmid(1), wi(1)*vbar(2)/vbar(1), vbar(1), &
 
  665                self%efield_dofs_work(:,2), self%j_dofs_local(:,2), &
 
  668           call self%kernel_smoother_1%evaluate &
 
  669                (xi(1), self%efield_dofs_work(1:self%n_dofs1,1), efield(1) )
 
  670           efield(1) = efield(1)*dt
 
  671           call self%kernel_smoother_0%add_charge( xi(1), &
 
  672                wi(1)* vbar(2)*dt, self%j_dofs_local(:,2) )
 
  673           call self%kernel_smoother_0%evaluate &
 
  674                (xi(1), self%efield_dofs_work(:,2), efield(2) )
 
  675           efield(2) = efield(2)*dt
 
  677        jmatrix = self%map%jacobian_matrix_inverse_transposed( [xmid(1), 0._f64, 0._f64] )
 
  679           vi(j) = vi(j) + qoverm *0.5_f64*((jmatrix(j,1)+jmat(j,1))*efield(1) + (jmatrix(j,2)+jmat(j,2))*efield(2))
 
  682        select case(self%boundary_particles)
 
  684           xnew = 2._f64*xbar-xnew
 
  688           call self%kernel_smoother_0%add_charge(xmid, wi(1), self%rhob)
 
  690           call self%kernel_smoother_0%add_charge(xmid, wi(1), self%rhob)
 
  691           xnew = modulo(xnew, 1._f64)
 
  693           call self%kernel_smoother_0%add_charge(xmid, -wi(1), self%rhob)
 
  695           xnew = modulo(xnew, 1._f64)
 
  698        if ( abs(vbar(1)) > 1.0d-16 ) 
then 
  699           call self%kernel_smoother_1%add_current_evaluate &
 
  700                ( xmid(1), xnew(1), wi(1), vbar(1), self%efield_dofs_work(1:self%n_dofs1,1), self%j_dofs_local(1:self%n_dofs1,1), &
 
  702           call self%kernel_smoother_0%add_current_evaluate &
 
  703                ( xmid(1), xnew(1), wi(1)*vbar(2)/vbar(1), vbar(1), &
 
  704                self%efield_dofs_work(:,2), self%j_dofs_local(:,2), &
 
  706           jmatrix = self%map%jacobian_matrix_inverse_transposed( [xnew(1), 0._f64, 0._f64] )
 
  708              vi(j) = vi(j) + qoverm *0.5_f64*((jmatrix(j,1)+jmat(j,1))*efield(1) + (jmatrix(j,2)+jmat(j,2))*efield(2))
 
  712        if ( abs(vbar(1)) > 1.0d-16 ) 
then 
  713           call self%kernel_smoother_1%add_current_evaluate &
 
  714                ( xi(1), xnew(1), wi(1), vbar(1), self%efield_dofs_work(1:self%n_dofs1,1), self%j_dofs_local(1:self%n_dofs1,1), &
 
  716           call self%kernel_smoother_0%add_current_evaluate &
 
  717                ( xi(1), xnew(1), wi(1)*vbar(2)/vbar(1), vbar(1), &
 
  718                self%efield_dofs_work(:,2), self%j_dofs_local(:,2), &
 
  721           call self%kernel_smoother_1%evaluate &
 
  722                (xi(1), self%efield_dofs_work(1:self%n_dofs1,1), efield(1) )
 
  723           efield(1) = efield(1)*dt
 
  724           call self%kernel_smoother_0%add_charge( xi(1), &
 
  725                wi(1)* vbar(2)*dt, self%j_dofs_local(:,2) )
 
  726           call self%kernel_smoother_0%evaluate &
 
  727                (xi(1), self%efield_dofs_work(:,2), efield(2) )
 
  728           efield(2) = efield(2)*dt
 
  730        jmatrix = self%map%jacobian_matrix_inverse_transposed( [xnew(1), 0._f64, 0._f64] )
 
  732           vi(j) = vi(j) + qoverm *0.5_f64*((jmatrix(j,1)+jmat(j,1))*efield(1) + (jmatrix(j,2)+jmat(j,2))*efield(2))
 
  752        boundary_particles, &
 
  754        iter_tolerance, max_iter, &
 
  763     sll_real64, 
target,                                   
intent( in )  :: efield_dofs(:,:) 
 
  764     sll_real64, 
target,                                   
intent( in )  :: bfield_dofs(:) 
 
  765     sll_real64,                                           
intent( in )  :: x_min 
 
  766     sll_real64,                                           
intent( in )  :: lx 
 
  768     sll_int32, 
optional,                                  
intent( in )  :: boundary_particles 
 
  769     sll_real64, 
optional,                                 
intent( in )  :: solver_tolerance 
 
  770     sll_real64, 
optional,                          
intent( in ) :: iter_tolerance 
 
  771     sll_int32,  
optional,                          
intent( in ) :: max_iter 
 
  772     sll_real64, 
optional,                                 
intent( in )  :: force_sign 
 
  773     sll_real64, 
optional, 
target,                  
intent( in ) :: rhob(:) 
 
  774     logical, 
optional,                                    
intent( in )  :: jmean
 
  778     if (
present(boundary_particles) )  
then 
  779        self%boundary_particles = boundary_particles
 
  782     if (
present(solver_tolerance) )  
then 
  783        self%solver_tolerance = solver_tolerance
 
  786     if( 
present(force_sign) )
then 
  787        self%force_sign = force_sign
 
  790     if (
present(jmean)) 
then 
  794     if (
present(iter_tolerance) )  
then 
  795        self%iter_tolerance = iter_tolerance
 
  798     if (
present(max_iter) )  
then 
  799        self%max_iter = max_iter
 
  802     self%maxwell_solver => maxwell_solver
 
  803     self%kernel_smoother_0 => kernel_smoother_0
 
  804     self%kernel_smoother_1 => kernel_smoother_1
 
  805     self%particle_group => particle_group
 
  806     self%efield_dofs => efield_dofs
 
  807     self%bfield_dofs => bfield_dofs
 
  811     sll_assert( self%kernel_smoother_0%n_cells == self%kernel_smoother_1%n_cells )
 
  812     sll_assert( self%kernel_smoother_0%n_cells == self%maxwell_solver%n_cells )
 
  815     self%n_cells = self%maxwell_solver%n_cells
 
  816     self%n_dofs0 = self%maxwell_solver%n_dofs0
 
  817     self%n_dofs1 = self%maxwell_solver%n_dofs1
 
  818     self%spline_degree = self%kernel_smoother_0%spline_degree
 
  820     sll_allocate( self%j_dofs(self%n_dofs0,2), ierr )
 
  821     sll_allocate( self%j_dofs_local(self%n_dofs0,2), ierr )
 
  822     sll_allocate( self%particle_mass_1_local(2*self%spline_degree-1, self%n_dofs1), ierr )
 
  823     sll_allocate( self%particle_mass_0_local(2*self%spline_degree+1, self%n_dofs0), ierr )
 
  824     self%j_dofs = 0.0_f64
 
  825     self%j_dofs_local = 0.0_f64
 
  826     self%particle_mass_1_local = 0.0_f64
 
  827     self%particle_mass_0_local = 0.0_f64
 
  829     if( self%n_cells+self%spline_degree == self%maxwell_solver%n_dofs0   ) 
then 
  830        self%boundary = .true.
 
  832        select type ( q => self%particle_mass_1 )
 
  834           call q%create( self%spline_degree-1, self%n_dofs1 )
 
  838        select type ( q => self%particle_mass_0 )
 
  840           call q%create( self%spline_degree, self%n_dofs0 )
 
  842     else if ( self%n_cells == self%maxwell_solver%n_dofs0 ) 
then 
  844        select type ( q => self%particle_mass_1 )
 
  846           call q%create( self%spline_degree-1, self%n_dofs1 )
 
  850        select type ( q => self%particle_mass_0 )
 
  852           call q%create( self%spline_degree, self%n_dofs0 )
 
  856     call self%linear_operator_1%create( self%maxwell_solver, self%particle_mass_1,  self%n_dofs1, self%maxwell_solver%s_deg_1 )
 
  857     call self%linear_solver_1%create( self%linear_operator_1 )
 
  858     self%linear_solver_1%atol = self%solver_tolerance/lx
 
  861     call self%linear_operator_0%create( self%maxwell_solver, self%particle_mass_0,  self%n_dofs0, self%maxwell_solver%s_deg_0 )
 
  862     call self%linear_solver_0%create( self%linear_operator_0 )
 
  863     self%linear_solver_0%atol = self%solver_tolerance
 
  866     self%n_particles_max = self%particle_group%group(1)%n_particles
 
  867     do j = 2,self%particle_group%n_species       
 
  868        self%n_particles_max = max(self%n_particles_max, self%particle_group%group(j)%n_particles )
 
  871     sll_allocate( self%xnew(self%particle_group%n_species,self%n_particles_max), ierr )
 
  872     sll_allocate( self%vnew(self%particle_group%n_species,2,self%n_particles_max), ierr )
 
  873     sll_allocate( self%efield_dofs_new(self%n_dofs0,2), ierr )
 
  874     sll_allocate( self%efield_dofs_work(self%n_dofs0,2), ierr )
 
  876     if( 
present(rhob) )
then 
  896        boundary_particles, &
 
  905     sll_real64, 
target,                                   
intent( in )  :: efield_dofs(:,:) 
 
  906     sll_real64, 
target,                                   
intent( in )  :: bfield_dofs(:) 
 
  907     sll_real64,                                           
intent( in )  :: x_min 
 
  908     sll_real64,                                           
intent( in )  :: lx 
 
  910     character(len=*),                                     
intent( in )  :: filename
 
  911     sll_int32, 
optional, 
intent( in )  :: boundary_particles 
 
  912     sll_real64, 
optional, 
intent(in) :: force_sign 
 
  913     sll_real64, 
optional, 
target,                  
intent( in ) :: rhob(:) 
 
  914     logical, 
optional, 
intent(in)    :: jmean
 
  916     character(len=256) :: file_prefix
 
  917     sll_int32 :: input_file, rank
 
  918     sll_int32 :: io_stat, io_stat0, io_stat1, file_id, boundary_particles_set, max_iter
 
  919     sll_real64 :: maxwell_tolerance, force_sign_set, iter_tolerance
 
  922     namelist /output/ file_prefix
 
  923     namelist /time_solver/ maxwell_tolerance
 
  924     namelist /time_iterate/ iter_tolerance, max_iter
 
  928     if (
present(boundary_particles)) 
then 
  929        boundary_particles_set = boundary_particles
 
  931        boundary_particles_set = 100
 
  934     if( 
present(force_sign) )
then 
  935        force_sign_set = force_sign
 
  937        force_sign_set = 1._f64
 
  940     if (
present(jmean)) 
then 
  947     open(newunit = input_file, file=filename, status=
'old',iostat=io_stat)
 
  948     if (io_stat /= 0) 
then 
  950           print*, 
'sll_m_time_propagator_pic_vm_1d2v_trafo_helper: Input file does not exist. Set default tolerance.' 
  951           open(newunit=file_id, file=trim(file_prefix)//
'_parameters_used.dat', position = 
'append', status=
'old', action=
'write', iostat=io_stat)
 
  952           write(file_id, *) 
'solver tolerance:', 1d-12
 
  953           write(file_id, *) 
'iter_tolerance:', 1d-10
 
  954           write(file_id, *) 
'max_iter:', 10
 
  955           write(file_id, *) 
'force_sign:', force_sign_set
 
  958        call self%init( maxwell_solver, &
 
  967             boundary_particles = boundary_particles_set, &
 
  968             force_sign=force_sign_set, &
 
  972        read(input_file, output, iostat=io_stat0)
 
  973        read(input_file, time_solver,iostat=io_stat)
 
  974        read(input_file, time_iterate,iostat=io_stat1)
 
  975        if (io_stat /= 0 .and. io_stat1 /= 0) 
then 
  977              print*, 
'sll_m_time_propagator_pic_vm_1d2v_trafo_helper: Tolerance not given. Set default tolerance.' 
  978              open(newunit=file_id, file=trim(file_prefix)//
'_parameters_used.dat', position = 
'append', status=
'old', action=
'write', iostat=io_stat)
 
  979              write(file_id, *) 
'solver tolerance:', 1d-12
 
  980              write(file_id, *) 
'iter_tolerance:', 1d-10
 
  981              write(file_id, *) 
'max_iter:', 10
 
  982              write(file_id, *) 
'force_sign:', force_sign_set
 
  985           call self%init( maxwell_solver, &
 
  994                boundary_particles = boundary_particles_set, &
 
  995                force_sign=force_sign_set, &
 
  998        else if (io_stat == 0 .and. io_stat1 /= 0) 
then 
 1000              open(newunit=file_id, file=trim(file_prefix)//
'_parameters_used.dat', position = 
'append', status=
'old', action=
'write', iostat=io_stat)
 
 1001              write(file_id, *) 
'solver tolerance:', maxwell_tolerance
 
 1002              write(file_id, *) 
'iter_tolerance:', 1d-10
 
 1003              write(file_id, *) 
'max_iter:', 10
 
 1004              write(file_id, *) 
'force_sign:', force_sign_set
 
 1007           call self%init( maxwell_solver, &
 
 1008                kernel_smoother_0, &
 
 1009                kernel_smoother_1, &
 
 1016                boundary_particles = boundary_particles_set, &
 
 1017                solver_tolerance=maxwell_tolerance,&
 
 1018                force_sign=force_sign_set, &
 
 1021        else if (io_stat /= 0 .and. io_stat1 == 0) 
then 
 1022           if (rank == 0 ) 
then 
 1023              open(newunit=file_id, file=trim(file_prefix)//
'_parameters_used.dat', position = 
'append', status=
'old', action=
'write', iostat=io_stat)
 
 1024              write(file_id, *) 
'solver tolerance:', 1d-12
 
 1025              write(file_id, *) 
'iter_tolerance:', iter_tolerance
 
 1026              write(file_id, *) 
'max_iter:', max_iter
 
 1027              write(file_id, *) 
'force_sign:', force_sign_set
 
 1030           call self%init( maxwell_solver, &
 
 1031                kernel_smoother_0, &
 
 1032                kernel_smoother_1, &
 
 1039                boundary_particles = boundary_particles_set, &
 
 1040                iter_tolerance=iter_tolerance, max_iter=max_iter, &
 
 1041                force_sign=force_sign_set, &
 
 1045           if (rank == 0 ) 
then 
 1046              open(newunit=file_id, file=trim(file_prefix)//
'_parameters_used.dat', position = 
'append', status=
'old', action=
'write', iostat=io_stat)
 
 1047              write(file_id, *) 
'solver tolerance:', maxwell_tolerance
 
 1048              write(file_id, *) 
'force_sign:', force_sign_set
 
 1049              write(file_id, *) 
'iter_tolerance:', iter_tolerance
 
 1050              write(file_id, *) 
'max_iter:', max_iter
 
 1053           call self%init( maxwell_solver, &
 
 1054                kernel_smoother_0, &
 
 1055                kernel_smoother_1, &
 
 1062                boundary_particles = boundary_particles_set, &
 
 1063                solver_tolerance=maxwell_tolerance,&
 
 1064                iter_tolerance=iter_tolerance, max_iter=max_iter, &
 
 1065                force_sign=force_sign_set, &
 
 1080     if( self%boundary ) 
then 
 1081        print*, 
'left boundary', self%counter_left
 
 1082        print*, 
'right boundary', self%counter_right
 
 1085     call self%linear_solver_1%free()
 
 1086     call self%linear_operator_1%free()
 
 1087     call self%particle_mass_1%free()
 
 1089     call self%linear_solver_0%free()
 
 1090     call self%linear_operator_0%free()
 
 1091     call self%particle_mass_0%free()
 
 1093     deallocate( self%j_dofs )
 
 1094     deallocate( self%j_dofs_local )
 
 1095     deallocate( self%particle_mass_1_local )
 
 1096     deallocate( self%particle_mass_0_local )
 
 1097     self%maxwell_solver => null()
 
 1098     self%kernel_smoother_0 => null()
 
 1099     self%kernel_smoother_1 => null()
 
 1100     self%particle_group => null()
 
 1101     self%efield_dofs => null()
 
 1102     self%bfield_dofs => null()
 
Combines values from all processes and distributes the result back to all processes.
integer(kind=i32) function, public sll_f_get_collective_rank(col)
Determines the rank of the calling process in the communicator.
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.
Gauss-Legendre integration.
real(kind=f64) function, dimension(2, 1:npoints), public sll_f_gauss_legendre_points_and_weights(npoints, a, b)
Returns a 2d array of size (2,npoints) containing gauss-legendre points and weights in the interval [...
module for conjugate gradient method in pure form
Module interfaces for coordinate transformation.
module for Compressed Sparse Row Matrix (CSR)
Module interface to solve Maxwell's equations in 1D.
Base class for kernel smoothers for accumulation and field evaluation in PIC.
Utilites for Maxwell solver's with spline finite elements using sparse matrix linear solvers.
subroutine, public sll_s_spline_fem_sparsity_mass(degree, n_cells, spmat)
Helper function to create sparsity pattern of the mass matrix.
Utilites for Maxwell solver's with spline finite elements.
subroutine, public sll_s_spline_fem_mass_line(degree, mass_line)
Computes the mass line for a mass matrix with degree splines.
Particle pusher based on antisymmetric splitting with AVF for 1d2v Vlasov-Poisson with coordinate tra...
subroutine delete_pic_vm_1d2v_trafo(self)
Destructor.
subroutine advect_e_pic_vm_1d2v_trafo(self, dt)
advect_e: Equations to be solved Solution with Schur complement: $ S_{+}=M_1+\frac{\Delta t^2 q^2}{4 ...
subroutine initialize_pic_vm_1d2v_trafo(self, maxwell_solver, kernel_smoother_0, kernel_smoother_1, particle_group, efield_dofs, bfield_dofs, x_min, Lx, map, boundary_particles, solver_tolerance, iter_tolerance, max_iter, force_sign, rhob, jmean)
Constructor.
subroutine compute_particle_boundary_current_evaluate(self, xi, xnew, vi, vbar, wi, qoverm, dt)
Helper function for advect_ex.
subroutine advect_x_pic_vm_1d2v_trafo(self, dt)
Finalization.
subroutine compute_particle_boundary(self, xold, xnew, vi)
Helper function for advect_x.
subroutine advect_eb_pic_vm_1d2v_trafo(self, dt)
advect_eb: Equations to be solved Solution with Schur complement: $ S=M_1+\frac{\Delta t^2}{4} D^\top...
subroutine initialize_file_pic_vm_1d2v_trafo(self, maxwell_solver, kernel_smoother_0, kernel_smoother_1, particle_group, efield_dofs, bfield_dofs, x_min, Lx, map, filename, boundary_particles, force_sign, rhob, jmean)
Constructor.
subroutine advect_ex_pic_vm_1d2v_trafo(self, dt)
advect_ex: Equations to be solved $\frac{\Xi^{n+1}-\Xi^n}{\Delta t}=\frac{DF^{-1}(\Xi^{n+1})+DF^{-1}(...
subroutine advect_vb_pic_vm_1d2v_trafo(self, dt)
advect_vb: Equations to be solved $V^{n+1}= (\cos(DF/J_F B)&\sin(DF/J_F B) \ -\sin(DF/J_F B) &\cos(DF...
Particle pusher based on antisymmetric splitting with AVF for 3d3v Vlasov-Maxwell with coordinate tra...
integer(kind=i32), parameter, public sll_p_boundary_particles_periodic
integer(kind=i32), parameter, public sll_p_boundary_particles_reflection
integer(kind=i32), parameter, public sll_p_boundary_particles_absorption
integer(kind=i32), parameter, public sll_p_boundary_particles_singular
class for the cg linear solver
type collecting functions for analytical coordinate mapping
Basic type of a kernel smoother used for PIC simulations.
Hamiltonian splitting type for Vlasov-Maxwell 1d2v.