module sym_boundary
  use datatype
  use model_info
  use mem_manager
  implicit none
  interface sym_boundary_x 
    module procedure sym_boundary_x_x, sym_boundary_x_xy, sym_boundary_x_xz, sym_boundary_x_xyz 
 end interface

  interface sym_boundary_y 
    module procedure sym_boundary_y_y, sym_boundary_y_xy, sym_boundary_y_yz, sym_boundary_y_xyz 
 end interface

  interface sym_boundary_z 
    module procedure sym_boundary_z_z, sym_boundary_z_xz, sym_boundary_z_yz, sym_boundary_z_xyz
 end interface

contains
  subroutine sym_boundary_x_x(var) 
    type(var_x), intent(inout) :: var
    integer :: i

    if (var%grid(1) == 0) then 
      do i = 1, margin_1
        work_x(plb1-i,:,:,var%id) = work_x(plb1+i,:,:,var%id) 
        work_x(pub1+i,:,:,var%id) = work_x(pub1-i,:,:,var%id) 
      end do

    else if (var%grid(1) == 1) then 
      do i = 0, margin_1
        work_x(plb1-i,:,:,var%id) = work_x(plb1+i+1,:,:,var%id) 
       end do
      do i = 1, margin_1
        work_x(pub1+i,:,:,var%id) = work_x(pub1-i+1,:,:,var%id) 
       end do
     end if
  end subroutine sym_boundary_x_x

  subroutine sym_boundary_x_xy(var) 
    type(var_xy), intent(inout) :: var
    integer :: i

    if (var%grid(1) == 0) then 
      do i = 1, margin_1
        work_xy(plb1-i,:,:,var%id) = work_xy(plb1+i,:,:,var%id) 
        work_xy(pub1+i,:,:,var%id) = work_xy(pub1-i,:,:,var%id) 
      end do

    else if (var%grid(1) == 1) then 
      do i = 0, margin_1
        work_xy(plb1-i,:,:,var%id) = work_xy(plb1+i+1,:,:,var%id) 
       end do
      do i = 1, margin_1
        work_xy(pub1+i,:,:,var%id) = work_xy(pub1-i+1,:,:,var%id) 
       end do
     end if
  end subroutine sym_boundary_x_xy

  subroutine sym_boundary_x_xz(var) 
    type(var_xz), intent(inout) :: var
    integer :: i

    if (var%grid(1) == 0) then 
      do i = 1, margin_1
        work_xz(plb1-i,:,:,var%id) = work_xz(plb1+i,:,:,var%id) 
        work_xz(pub1+i,:,:,var%id) = work_xz(pub1-i,:,:,var%id) 
      end do

    else if (var%grid(1) == 1) then 
      do i = 0, margin_1
        work_xz(plb1-i,:,:,var%id) = work_xz(plb1+i+1,:,:,var%id) 
       end do
      do i = 1, margin_1
        work_xz(pub1+i,:,:,var%id) = work_xz(pub1-i+1,:,:,var%id) 
       end do
     end if
  end subroutine sym_boundary_x_xz

  subroutine sym_boundary_x_xyz(var) 
    type(var_xyz), intent(inout) :: var
    integer :: i

    if (var%grid(1) == 0) then 
      do i = 1, margin_1
        work_xyz(plb1-i,:,:,var%id) = work_xyz(plb1+i,:,:,var%id) 
        work_xyz(pub1+i,:,:,var%id) = work_xyz(pub1-i,:,:,var%id) 
      end do

    else if (var%grid(1) == 1) then 
      do i = 0, margin_1
        work_xyz(plb1-i,:,:,var%id) = work_xyz(plb1+i+1,:,:,var%id) 
       end do
      do i = 1, margin_1
        work_xyz(pub1+i,:,:,var%id) = work_xyz(pub1-i+1,:,:,var%id) 
       end do
     end if
  end subroutine sym_boundary_x_xyz

  subroutine sym_boundary_y_y(var) 
    type(var_y), intent(inout) :: var
    integer :: i

    if (var%grid(2) == 0) then 
      do i = 1, margin_2
        work_y(:,plb2-i,:,var%id) = work_y(:,plb2+i,:,var%id) 
        work_y(:,pub2+i,:,var%id) = work_y(:,pub2-i,:,var%id) 
      end do

    else if (var%grid(2) == 1) then 
      do i = 0, margin_2
        work_y(:,plb2-i,:,var%id) = work_y(:,plb2+i+1,:,var%id) 
       end do
      do i = 1, margin_2
        work_y(:,pub2+i,:,var%id) = work_y(:,pub2-i+1,:,var%id) 
       end do
     end if
  end subroutine sym_boundary_y_y

  subroutine sym_boundary_y_xy(var) 
    type(var_xy), intent(inout) :: var
    integer :: i

    if (var%grid(2) == 0) then 
      do i = 1, margin_2
        work_xy(:,plb2-i,:,var%id) = work_xy(:,plb2+i,:,var%id) 
        work_xy(:,pub2+i,:,var%id) = work_xy(:,pub2-i,:,var%id) 
      end do

    else if (var%grid(2) == 1) then 
      do i = 0, margin_2
        work_xy(:,plb2-i,:,var%id) = work_xy(:,plb2+i+1,:,var%id) 
       end do
      do i = 1, margin_2
        work_xy(:,pub2+i,:,var%id) = work_xy(:,pub2-i+1,:,var%id) 
       end do
     end if
  end subroutine sym_boundary_y_xy

  subroutine sym_boundary_y_yz(var) 
    type(var_yz), intent(inout) :: var
    integer :: i

    if (var%grid(2) == 0) then 
      do i = 1, margin_2
        work_yz(:,plb2-i,:,var%id) = work_yz(:,plb2+i,:,var%id) 
        work_yz(:,pub2+i,:,var%id) = work_yz(:,pub2-i,:,var%id) 
      end do

    else if (var%grid(2) == 1) then 
      do i = 0, margin_2
        work_yz(:,plb2-i,:,var%id) = work_yz(:,plb2+i+1,:,var%id) 
       end do
      do i = 1, margin_2
        work_yz(:,pub2+i,:,var%id) = work_yz(:,pub2-i+1,:,var%id) 
       end do
     end if
  end subroutine sym_boundary_y_yz

  subroutine sym_boundary_y_xyz(var) 
    type(var_xyz), intent(inout) :: var
    integer :: i

    if (var%grid(2) == 0) then 
      do i = 1, margin_2
        work_xyz(:,plb2-i,:,var%id) = work_xyz(:,plb2+i,:,var%id) 
        work_xyz(:,pub2+i,:,var%id) = work_xyz(:,pub2-i,:,var%id) 
      end do

    else if (var%grid(2) == 1) then 
      do i = 0, margin_2
        work_xyz(:,plb2-i,:,var%id) = work_xyz(:,plb2+i+1,:,var%id) 
       end do
      do i = 1, margin_2
        work_xyz(:,pub2+i,:,var%id) = work_xyz(:,pub2-i+1,:,var%id) 
       end do
     end if
  end subroutine sym_boundary_y_xyz

  subroutine sym_boundary_z_z(var) 
    type(var_z), intent(inout) :: var
    integer :: i

    if (var%grid(3) == 0) then 
      do i = 1, margin_3
        work_z(:,:,plb3-i,var%id) = work_z(:,:,plb3+i,var%id) 
        work_z(:,:,pub3+i,var%id) = work_z(:,:,pub3-i,var%id) 
      end do

    else if (var%grid(3) == 1) then 
      do i = 0, margin_3
        work_z(:,:,plb3-i,var%id) = work_z(:,:,plb3+i+1,var%id) 
       end do
      do i = 1, margin_3
        work_z(:,:,pub3+i,var%id) = work_z(:,:,pub3-i+1,var%id) 
       end do
     end if
  end subroutine sym_boundary_z_z

  subroutine sym_boundary_z_xz(var) 
    type(var_xz), intent(inout) :: var
    integer :: i

    if (var%grid(3) == 0) then 
      do i = 1, margin_3
        work_xz(:,:,plb3-i,var%id) = work_xz(:,:,plb3+i,var%id) 
        work_xz(:,:,pub3+i,var%id) = work_xz(:,:,pub3-i,var%id) 
      end do

    else if (var%grid(3) == 1) then 
      do i = 0, margin_3
        work_xz(:,:,plb3-i,var%id) = work_xz(:,:,plb3+i+1,var%id) 
       end do
      do i = 1, margin_3
        work_xz(:,:,pub3+i,var%id) = work_xz(:,:,pub3-i+1,var%id) 
       end do
     end if
  end subroutine sym_boundary_z_xz

  subroutine sym_boundary_z_yz(var) 
    type(var_yz), intent(inout) :: var
    integer :: i

    if (var%grid(3) == 0) then 
      do i = 1, margin_3
        work_yz(:,:,plb3-i,var%id) = work_yz(:,:,plb3+i,var%id) 
        work_yz(:,:,pub3+i,var%id) = work_yz(:,:,pub3-i,var%id) 
      end do

    else if (var%grid(3) == 1) then 
      do i = 0, margin_3
        work_yz(:,:,plb3-i,var%id) = work_yz(:,:,plb3+i+1,var%id) 
       end do
      do i = 1, margin_3
        work_yz(:,:,pub3+i,var%id) = work_yz(:,:,pub3-i+1,var%id) 
       end do
     end if
  end subroutine sym_boundary_z_yz

  subroutine sym_boundary_z_xyz(var) 
    type(var_xyz), intent(inout) :: var
    integer :: i

    if (var%grid(3) == 0) then 
      do i = 1, margin_3
        work_xyz(:,:,plb3-i,var%id) = work_xyz(:,:,plb3+i,var%id) 
        work_xyz(:,:,pub3+i,var%id) = work_xyz(:,:,pub3-i,var%id) 
      end do

    else if (var%grid(3) == 1) then 
      do i = 0, margin_3
        work_xyz(:,:,plb3-i,var%id) = work_xyz(:,:,plb3+i+1,var%id) 
       end do
      do i = 1, margin_3
        work_xyz(:,:,pub3+i,var%id) = work_xyz(:,:,pub3-i+1,var%id) 
       end do
     end if
  end subroutine sym_boundary_z_xyz

end module sym_boundary
