util.f90 Source File


This file depends on

sourcefile~~util.f90~~EfferentGraph sourcefile~util.f90 util.f90 sourcefile~precision_def.f90 precision_def.F90 sourcefile~util.f90->sourcefile~precision_def.f90 sourcefile~code_util.f90 code_util.f90 sourcefile~util.f90->sourcefile~code_util.f90 sourcefile~code_util.f90->sourcefile~precision_def.f90

Files dependent on this one

sourcefile~~util.f90~~AfferentGraph sourcefile~util.f90 util.f90 sourcefile~init_part_distrib.f90 init_part_distrib.f90 sourcefile~init_part_distrib.f90->sourcefile~util.f90 sourcefile~env_evolve_in_time.f90 env_evolve_in_time.f90 sourcefile~env_evolve_in_time.f90->sourcefile~util.f90 sourcefile~ionize.f90 ionize.f90 sourcefile~env_evolve_in_time.f90->sourcefile~ionize.f90 sourcefile~window.f90 window.f90 sourcefile~env_evolve_in_time.f90->sourcefile~window.f90 sourcefile~mpi_part_interface.f90 mpi_part_interface.f90 sourcefile~env_evolve_in_time.f90->sourcefile~mpi_part_interface.f90 sourcefile~fluid_density_momenta.f90 fluid_density_momenta.f90 sourcefile~env_evolve_in_time.f90->sourcefile~fluid_density_momenta.f90 sourcefile~curr_and_fields_util.f90 curr_and_fields_util.f90 sourcefile~env_evolve_in_time.f90->sourcefile~curr_and_fields_util.f90 sourcefile~init_beam_part_distrib.f90 init_beam_part_distrib.f90 sourcefile~init_beam_part_distrib.f90->sourcefile~util.f90 sourcefile~mpi_curr_interface.f90 mpi_curr_interface.f90 sourcefile~init_beam_part_distrib.f90->sourcefile~mpi_curr_interface.f90 sourcefile~mpi_field_interface.f90 mpi_field_interface.f90 sourcefile~init_beam_part_distrib.f90->sourcefile~mpi_field_interface.f90 sourcefile~psolve.f90 psolve.f90 sourcefile~init_beam_part_distrib.f90->sourcefile~psolve.f90 sourcefile~ionize.f90->sourcefile~util.f90 sourcefile~parallel.f90 parallel.F90 sourcefile~parallel.f90->sourcefile~util.f90 sourcefile~window.f90->sourcefile~util.f90 sourcefile~window.f90->sourcefile~mpi_field_interface.f90 sourcefile~run_data_info.f90 run_data_info.f90 sourcefile~window.f90->sourcefile~run_data_info.f90 sourcefile~window.f90->sourcefile~mpi_part_interface.f90 sourcefile~pic_evolve_in_time.f90 pic_evolve_in_time.f90 sourcefile~pic_evolve_in_time.f90->sourcefile~ionize.f90 sourcefile~pic_evolve_in_time.f90->sourcefile~window.f90 sourcefile~pic_evolve_in_time.f90->sourcefile~mpi_part_interface.f90 sourcefile~pic_evolve_in_time.f90->sourcefile~fluid_density_momenta.f90 sourcefile~pic_evolve_in_time.f90->sourcefile~curr_and_fields_util.f90 sourcefile~grid_fields.f90 grid_fields.f90 sourcefile~grid_fields.f90->sourcefile~parallel.f90 sourcefile~pic_in.f90 pic_in.f90 sourcefile~pic_in.f90->sourcefile~init_part_distrib.f90 sourcefile~init_laser_field.f90 init_laser_field.f90 sourcefile~pic_in.f90->sourcefile~init_laser_field.f90 sourcefile~start_all.f90 start_all.F90 sourcefile~start_all.f90->sourcefile~ionize.f90 sourcefile~start_all.f90->sourcefile~pic_in.f90 sourcefile~start_all.f90->sourcefile~run_data_info.f90 sourcefile~pic_dump.f90 pic_dump.f90 sourcefile~start_all.f90->sourcefile~pic_dump.f90 sourcefile~mpi_curr_interface.f90->sourcefile~parallel.f90 sourcefile~prl_fft.f90 prl_fft.f90 sourcefile~prl_fft.f90->sourcefile~parallel.f90 sourcefile~aladyn.f90 ALaDyn.F90 sourcefile~aladyn.f90->sourcefile~env_evolve_in_time.f90 sourcefile~aladyn.f90->sourcefile~init_beam_part_distrib.f90 sourcefile~aladyn.f90->sourcefile~pic_evolve_in_time.f90 sourcefile~aladyn.f90->sourcefile~start_all.f90 sourcefile~pic_out.f90 pic_out.f90 sourcefile~aladyn.f90->sourcefile~pic_out.f90 sourcefile~aladyn.f90->sourcefile~run_data_info.f90 sourcefile~diag_part_and_fields.f90 diag_part_and_fields.f90 sourcefile~aladyn.f90->sourcefile~diag_part_and_fields.f90 sourcefile~pic_out_util.f90 pic_out_util.f90 sourcefile~aladyn.f90->sourcefile~pic_out_util.f90 sourcefile~pic_out.f90->sourcefile~parallel.f90 sourcefile~mpi_field_interface.f90->sourcefile~parallel.f90 sourcefile~run_data_info.f90->sourcefile~parallel.f90 sourcefile~mpi_part_interface.f90->sourcefile~parallel.f90 sourcefile~pic_dump.f90->sourcefile~parallel.f90 sourcefile~diag_part_and_fields.f90->sourcefile~parallel.f90 sourcefile~fluid_density_momenta.f90->sourcefile~grid_fields.f90 sourcefile~fluid_density_momenta.f90->sourcefile~mpi_field_interface.f90 sourcefile~curr_and_fields_util.f90->sourcefile~grid_fields.f90 sourcefile~curr_and_fields_util.f90->sourcefile~mpi_curr_interface.f90 sourcefile~curr_and_fields_util.f90->sourcefile~mpi_field_interface.f90 sourcefile~init_laser_field.f90->sourcefile~grid_fields.f90 sourcefile~psolve.f90->sourcefile~grid_fields.f90 sourcefile~psolve.f90->sourcefile~prl_fft.f90 sourcefile~pic_out_util.f90->sourcefile~mpi_curr_interface.f90 sourcefile~pic_out_util.f90->sourcefile~mpi_field_interface.f90 sourcefile~pic_out_util.f90->sourcefile~psolve.f90

Contents

Source Code


Source Code

!*****************************************************************************************************!
!                            Copyright 2008-2020  The ALaDyn Collaboration                            !
!*****************************************************************************************************!

!*****************************************************************************************************!
!  This file is part of ALaDyn.                                                                       !
!                                                                                                     !
!  ALaDyn is free software: you can redistribute it and/or modify                                     !
!  it under the terms of the GNU General Public License as published by                               !
!  the Free Software Foundation, either version 3 of the License, or                                  !
!  (at your option) any later version.                                                                !
!                                                                                                     !
!  ALaDyn is distributed in the hope that it will be useful,                                          !
!  but WITHOUT ANY WARRANTY; without even the implied warranty of                                     !
!  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                      !
!  GNU General Public License for more details.                                                       !
!                                                                                                     !
!  You should have received a copy of the GNU General Public License                                  !
!  along with ALaDyn.  If not, see <http://www.gnu.org/licenses/>.                                    !
!*****************************************************************************************************!

 module util

  use precision_def
  use code_util

  implicit none
  private
  public :: gasdev, init_random_seed, bunch_gen

 contains

  subroutine init_random_seed(myrank)
   integer, intent(in) :: myrank
   integer, allocatable :: seed(:)
   integer :: i, n, un, istat, dt(8), pid, t(2), s
   integer(8) :: count, tms

   i = 0
   call random_seed(size=n)
   allocate (seed(n))

   if (.not. l_disable_rng_seed) then
    un = 123
    ! First try if the OS provides a random number generator
    open (unit=un, file='/dev/urandom', access='stream', &
          form='unformatted', action='read', status='old', iostat=istat)
    if (istat == 0) then
     read (un) seed
     close (un)
    else
     ! Fallback to XOR:ing the current time and pid. The PID is
     ! useful in case one launches multiple instances of the same
     ! program in parallel.
     call system_clock(count)
     if (count /= 0) then
      t = transfer(count, t)
     else
      call date_and_time(values=dt)
      tms = (dt(1) - 1970)*365_8*24*60*60*1000 + dt(2)*31_8*24*60*60*1000 &
            + dt(3)*24*60*60*60*1000 + dt(5)*60*60*1000 + dt(6)*60*1000 + &
            dt(7)*1000 + dt(8)
      t = transfer(tms, t)
     end if
     s = ieor(t(1), t(2))
     pid = myrank + 1099279 ! Add a prime
     s = ieor(s, pid)
     if (n >= 3) then
      seed(1) = t(1) + 36269
      seed(2) = t(2) + 72551
      seed(3) = pid
      if (n > 3) then
       seed(4:) = s + 37*[(i, i=0, n - 4)]
      end if
     else
      seed = s + 37*[(i, i=0, n - 1)]
     end if
    end if
   else
    seed = myrank
   end if
   call random_seed(put=seed)
  end subroutine
  !========================

  subroutine gasdev(dev)

   real(dp), intent(out) :: dev
   real(dp) :: v1, v2, rsq
   real(dp), save :: g
   logical, save :: gaus_store = .false.

   if (gaus_store) then
    dev = g
    gaus_store = .false.
   else
    do
     call random_number(v1)
     call random_number(v2)
     v1 = 2.0*v1 - 1.0
     v2 = 2.0*v2 - 1.0
     rsq = v1*v1 + v2*v2
     if (rsq < 1.0) exit
    end do
    rsq = sqrt(-2.0*log(rsq)/rsq)
    dev = v1*rsq
    g = v2*rsq
    gaus_store = .true.
   end if
  end subroutine

  !===============================

  subroutine sort(part, np)

   real(dp), intent(inout) :: part(:)
   integer, intent(in) :: np
   integer :: ir, i, j, k, l, jstack
   integer, parameter :: m = 7, nstack = 50
   real(dp) :: a
   integer :: istack(nstack)

   jstack = 0
   ir = np
   l = 1
   do
    if (ir - l < m) then
     do j = l + 1, ir
      a = part(j)
      do i = j - 1, l, -1
       if (part(i) <= a) exit
       part(i + 1) = part(i)
      end do
      part(i + 1) = a
     end do
     if (jstack == 0) return
     ir = istack(jstack)
     l = istack(jstack - 1)
     jstack = jstack - 2
    else
     k = (l + ir)/2
     call swap(k, l + 1)

     if (part(l) > part(ir)) call swap(l, ir)
     if (part(l + 1) > part(ir)) call swap(l + 1, ir)
     if (part(l) > part(l + 1)) call swap(l, l + 1)

     i = l + 1
     j = ir
     a = part(l + 1)
     do
      do
       i = i + 1
       if (part(i) >= a) exit
      end do
      do
       j = j - 1
       if (part(j) <= a) exit
      end do
      if (j < i) exit
      call swap(i, j)
     end do
     part(l + 1) = part(j)
     part(j) = a
     jstack = jstack + 2
     if (jstack > nstack) exit
     if (ir - i + 1 >= j - l) then
      istack(jstack) = ir
      istack(jstack - 1) = i
      ir = j - 1
     else
      istack(jstack) = j - 1
      istack(jstack - 1) = l
      l = i
     end if
    end if
   end do

  contains

   subroutine swap(i1, i2)
    integer, intent(in) :: i1, i2
    real(dp) :: temp

    temp = part(i1)
    part(i1) = part(i2)
    part(i2) = temp

   end subroutine

  end subroutine

  !=========================

  subroutine vsort(part, np, ndv, dir)

   real(dp), intent(inout) :: part(:, :)
   integer, intent(in) :: np, ndv, dir
   integer :: ir, i, j, k, l, jstack
   integer, parameter :: m = 7, nstack = 50
   real(dp) :: a(ndv), temp(ndv)
   integer :: istack(nstack)

   jstack = 0
   ir = np
   l = 1
   do
    if (ir - l < m) then
     do j = l + 1, ir
      a(1:ndv) = part(1:ndv, j)
      do i = j - 1, l, -1
       if (part(dir, i) <= a(dir)) exit
       part(1:ndv, i + 1) = part(1:ndv, i)
      end do
      part(1:ndv, i + 1) = a(1:ndv)
     end do
     if (jstack == 0) return
     ir = istack(jstack)
     l = istack(jstack - 1)
     jstack = jstack - 2
    else
     k = (l + ir)/2
     call swap(k, l + 1, ndv)

     if (part(dir, l) > part(dir, ir)) call swap(l, ir, ndv)
     if (part(dir, l + 1) > part(dir, ir)) call swap(l + 1, ir, ndv)
     if (part(dir, l) > part(dir, l + 1)) call swap(l, l + 1, ndv)

     i = l + 1
     j = ir
     a(1:ndv) = part(1:ndv, l + 1)
     do
      do
       i = i + 1
       if (part(dir, i) >= a(dir)) exit
      end do
      do
       j = j - 1
       if (part(dir, j) <= a(dir)) exit
      end do
      if (j < i) exit
      call swap(i, j, ndv)
     end do
     part(1:ndv, l + 1) = part(1:ndv, j)
     part(1:ndv, j) = a(1:ndv)
     jstack = jstack + 2
     if (jstack > nstack) exit
     if (ir - i + 1 >= j - l) then
      istack(jstack) = ir
      istack(jstack - 1) = i
      ir = j - 1
     else
      istack(jstack) = j - 1
      istack(jstack - 1) = l
      l = i
     end if
    end if
   end do

  contains

   subroutine swap(i1, i2, nd)
    integer, intent(in) :: i1, i2, nd

    temp(1:nd) = part(1:nd, i1)
    part(1:nd, i1) = part(1:nd, i2)
    part(1:nd, i2) = temp(1:nd)

   end subroutine

  end subroutine

  !===========================
  subroutine bunch_gen(ndm, n1, n2, sx, sy, sz, gm, ey, ez, cut, dg, &
                       bunch)
   integer, intent(in) :: ndm, n1, n2
   real(dp), intent(in) :: sx, sy, sz, gm, ey, ez, cut, dg
   real(dp), intent(inout) :: bunch(:, :)
   integer :: i, j, np
   real(dp) :: sigs(6)
   real(dp) :: xm, ym, zm, pxm, pym, pzm
   real(dp) :: v1, v2, rnd, a, np_norm

   !============= ey,ez are emittances (in mm-microns)
   ! FIX emittances are ALWAYS a dimension times an angle...
   ! so this (in mm-micron) doesn't make any sense
   ! dg=d(gamma)/gamma (%)
   ! dp_y=ey/s_y dp_z=ez/s_z dp_x=d(gamma)
   !=============================================

   !Distribute (x,y,z,px,py,pz) centered on 0; px=> px+gamma

   select case (ndm)
   case (2)
    sigs(1) = sx
    sigs(2) = sy
    sigs(3) = sqrt(3.0)*0.01*dg*gm !dpz
    sigs(4) = ey/sy
    do i = n1, n2
     do
      call random_number(v1)
      call random_number(v2)
      v1 = 2.0*v1 - 1.0
      v2 = 2.0*v2 - 1.0
      rnd = v1*v1 + v2*v2
      if (rnd < 1.0) exit
     end do
     rnd = sqrt(-2.0*log(rnd)/rnd)
     bunch(i, 2) = v1*rnd
     bunch(i, 4) = v2*rnd
     call gasdev(rnd)
     bunch(i, 1) = rnd
     do
      call random_number(rnd)
      rnd = 2.*rnd - 1.
      a = cut*rnd
      if (a*a < 1.) exit
     end do
     bunch(i, 3) = a
    end do
    do j = 1, 4
     bunch(n1:n2, j) = sigs(j)*bunch(n1:n2, j)
    end do
    bunch(n1:n2, 3) = bunch(n1:n2, 3) + gm
    xm = 0.0
    ym = 0.0
    pxm = 0.0
    pym = 0.0
    ! Reset centering
    xm = sum(bunch(n1:n2, 1))
    ym = sum(bunch(n1:n2, 2))
    pxm = sum(bunch(n1:n2, 3))
    pym = sum(bunch(n1:n2, 4))

    np = n2 + 1 - n1
    xm = xm/real(np, dp)
    ym = ym/real(np, dp)
    pxm = pxm/real(np, dp)
    pym = pym/real(np, dp)
    do i = n1, n2
     bunch(i, 1) = bunch(i, 1) - xm
     bunch(i, 2) = bunch(i, 2) - ym
     bunch(i, 3) = bunch(i, 3) - (pxm - gm)
     bunch(i, 4) = bunch(i, 4) - pym
    end do
   case (3)
    sigs(1) = sx
    sigs(2) = sy
    sigs(3) = sz
    sigs(4) = sqrt(3.0)*0.01*dg*gm !dpz
    sigs(5) = ey/sy
    sigs(6) = ez/sz
    do j = 2, 5, 3
     do i = n1, n2
      do
       call random_number(v1)
       call random_number(v2)
       v1 = 2.0*v1 - 1.0
       v2 = 2.0*v2 - 1.0
       rnd = v1*v1 + v2*v2
       if (rnd < 1.0) exit
      end do
      rnd = sqrt(-2.0*log(rnd)/rnd)
      bunch(i, j) = v1*rnd
      bunch(i, j + 1) = v2*rnd
     end do
    enddo
    j = 1
    do i = n1, n2
     call gasdev(rnd)
     bunch(i, j) = rnd
     do
      call random_number(rnd)
      rnd = 2.*rnd - 1.
      a = cut*rnd
      if (a*a < 1.) exit
     end do
     bunch(i, j + 3) = a
    end do
!======================
    do j = 1, 6
     do i = n1, n2
      bunch(i, j) = sigs(j)*bunch(i, j)
     end do
    end do
    bunch(n1:n2, 4) = bunch(n1:n2, 4) + gm

    xm = 0.0
    ym = 0.0
    zm = 0.0
    pxm = 0.0
    pym = 0.0
    pzm = 0.0

    ! Reset centering
    np = n2 + 1 - n1
    np_norm = 1./real(np, dp)
    xm = np_norm*sum(bunch(n1:n2, 1))
    ym = np_norm*sum(bunch(n1:n2, 2))
    zm = np_norm*sum(bunch(n1:n2, 3))
    pxm = np_norm*sum(bunch(n1:n2, 4))
    pym = np_norm*sum(bunch(n1:n2, 5))
    pzm = np_norm*sum(bunch(n1:n2, 6))

    do i = n1, n2
     bunch(i, 1) = bunch(i, 1) - xm
     bunch(i, 2) = bunch(i, 2) - ym
     bunch(i, 3) = bunch(i, 3) - zm
     bunch(i, 4) = bunch(i, 4) - (pxm - gm)
     bunch(i, 5) = bunch(i, 5) - pym
     bunch(i, 6) = bunch(i, 6) - pzm
    end do
   end select
  end subroutine

 end module