module gms_assign
  use datatype
  use mem_manager
  implicit none
  integer :: ix, iy, iz

  interface assignment(=)
    module procedure data_data_equal_x_x
    module procedure data_data_equal_y_y
    module procedure data_data_equal_z_z
    module procedure data_data_equal_xy_x
    module procedure data_data_equal_xy_y
    module procedure data_data_equal_xy_xy
    module procedure data_data_equal_xz_x
    module procedure data_data_equal_xz_z
    module procedure data_data_equal_xz_xz
    module procedure data_data_equal_yz_y
    module procedure data_data_equal_yz_z
    module procedure data_data_equal_yz_yz
    module procedure data_data_equal_xyz_x
    module procedure data_data_equal_xyz_y
    module procedure data_data_equal_xyz_z
    module procedure data_data_equal_xyz_xy
    module procedure data_data_equal_xyz_xz
    module procedure data_data_equal_xyz_yz
    module procedure data_data_equal_xyz_xyz
  end interface
contains

  subroutine data_data_equal_x_x(output, input)
    type(var_x), intent(inout) :: output 
    type(var_x), intent(in) :: input 

    if ( input%grid(1) /= output%grid(1) ) stop "(=)grid violation"

    linked_counter_x( output%id ) = linked_counter_x( output%id ) -1 

    if ( linked_counter_x( output%id ) == 0 ) then 
       free_mask_x( output%id ) = .true. 
    end if 

    output%id = input%id 

       linked_counter_x( input%id ) = linked_counter_x( input%id ) + 1 

    if( free_mask_x( input%id )  ) then 
       free_mask_x( input%id ) = .false.
    end if 

    call garbege_collect

  end subroutine data_data_equal_x_x

  subroutine data_data_equal_y_y(output, input)
    type(var_y), intent(inout) :: output 
    type(var_y), intent(in) :: input 

    if ( input%grid(2) /= output%grid(2) ) stop "(=)grid violation"

    linked_counter_y( output%id ) = linked_counter_y( output%id ) -1 

    if ( linked_counter_y( output%id ) == 0 ) then 
       free_mask_y( output%id ) = .true. 
    end if 

    output%id = input%id 

       linked_counter_y( input%id ) = linked_counter_y( input%id ) + 1 

    if( free_mask_y( input%id )  ) then 
       free_mask_y( input%id ) = .false.
    end if 

    call garbege_collect

  end subroutine data_data_equal_y_y

  subroutine data_data_equal_z_z(output, input)
    type(var_z), intent(inout) :: output 
    type(var_z), intent(in) :: input 

    if ( input%grid(3) /= output%grid(3) ) stop "(=)grid violation"

    linked_counter_z( output%id ) = linked_counter_z( output%id ) -1 

    if ( linked_counter_z( output%id ) == 0 ) then 
       free_mask_z( output%id ) = .true. 
    end if 

    output%id = input%id 

       linked_counter_z( input%id ) = linked_counter_z( input%id ) + 1 

    if( free_mask_z( input%id )  ) then 
       free_mask_z( input%id ) = .false.
    end if 

    call garbege_collect

  end subroutine data_data_equal_z_z

  subroutine data_data_equal_xy_x(output, input)
    type(var_xy), intent(inout) :: output 
    type(var_x), intent(in) :: input 

    if ( input%grid(1) /= output%grid(1) ) stop "(=)grid violation"

      do iy = lb_axis2, ub_axis2
        do ix = lb_axis1, ub_axis1

        work_xy(ix, iy, 1, output%id) & 
                      = work_x(ix, 1, 1, input%id)  

      end do
    end do

    call garbege_collect

  end subroutine data_data_equal_xy_x

  subroutine data_data_equal_xy_y(output, input)
    type(var_xy), intent(inout) :: output 
    type(var_y), intent(in) :: input 

    if ( input%grid(2) /= output%grid(2) ) stop "(=)grid violation"

      do iy = lb_axis2, ub_axis2
        do ix = lb_axis1, ub_axis1

        work_xy(ix, iy, 1, output%id) & 
                      = work_y(1, iy, 1, input%id)  

      end do
    end do

    call garbege_collect

  end subroutine data_data_equal_xy_y

  subroutine data_data_equal_xy_xy(output, input)
    type(var_xy), intent(inout) :: output 
    type(var_xy), intent(in) :: input 

    if ( input%grid(1) /= output%grid(1) ) stop "(=)grid violation"
    if ( input%grid(2) /= output%grid(2) ) stop "(=)grid violation"

    linked_counter_xy( output%id ) = linked_counter_xy( output%id ) -1 

    if ( linked_counter_xy( output%id ) == 0 ) then 
       free_mask_xy( output%id ) = .true. 
    end if 

    output%id = input%id 

       linked_counter_xy( input%id ) = linked_counter_xy( input%id ) + 1 

    if( free_mask_xy( input%id )  ) then 
       free_mask_xy( input%id ) = .false.
    end if 

    call garbege_collect

  end subroutine data_data_equal_xy_xy

  subroutine data_data_equal_xz_x(output, input)
    type(var_xz), intent(inout) :: output 
    type(var_x), intent(in) :: input 

    if ( input%grid(1) /= output%grid(1) ) stop "(=)grid violation"

    do iz = lb_axis3, ub_axis3
        do ix = lb_axis1, ub_axis1

        work_xz(ix, 1, iz, output%id) & 
                      = work_x(ix, 1, 1, input%id)  

        end do
    end do

    call garbege_collect

  end subroutine data_data_equal_xz_x

  subroutine data_data_equal_xz_z(output, input)
    type(var_xz), intent(inout) :: output 
    type(var_z), intent(in) :: input 

    if ( input%grid(3) /= output%grid(3) ) stop "(=)grid violation"

    do iz = lb_axis3, ub_axis3
        do ix = lb_axis1, ub_axis1

        work_xz(ix, 1, iz, output%id) & 
                      = work_z(1, 1, iz, input%id)  

        end do
    end do

    call garbege_collect

  end subroutine data_data_equal_xz_z

  subroutine data_data_equal_xz_xz(output, input)
    type(var_xz), intent(inout) :: output 
    type(var_xz), intent(in) :: input 

    if ( input%grid(1) /= output%grid(1) ) stop "(=)grid violation"
    if ( input%grid(3) /= output%grid(3) ) stop "(=)grid violation"

    linked_counter_xz( output%id ) = linked_counter_xz( output%id ) -1 

    if ( linked_counter_xz( output%id ) == 0 ) then 
       free_mask_xz( output%id ) = .true. 
    end if 

    output%id = input%id 

       linked_counter_xz( input%id ) = linked_counter_xz( input%id ) + 1 

    if( free_mask_xz( input%id )  ) then 
       free_mask_xz( input%id ) = .false.
    end if 

    call garbege_collect

  end subroutine data_data_equal_xz_xz

  subroutine data_data_equal_yz_y(output, input)
    type(var_yz), intent(inout) :: output 
    type(var_y), intent(in) :: input 

    if ( input%grid(2) /= output%grid(2) ) stop "(=)grid violation"

    do iz = lb_axis3, ub_axis3
      do iy = lb_axis2, ub_axis2

        work_yz(1, iy, iz, output%id) & 
                      = work_y(1, iy, 1, input%id)  

        end do
      end do

    call garbege_collect

  end subroutine data_data_equal_yz_y

  subroutine data_data_equal_yz_z(output, input)
    type(var_yz), intent(inout) :: output 
    type(var_z), intent(in) :: input 

    if ( input%grid(3) /= output%grid(3) ) stop "(=)grid violation"

    do iz = lb_axis3, ub_axis3
      do iy = lb_axis2, ub_axis2

        work_yz(1, iy, iz, output%id) & 
                      = work_z(1, 1, iz, input%id)  

        end do
      end do

    call garbege_collect

  end subroutine data_data_equal_yz_z

  subroutine data_data_equal_yz_yz(output, input)
    type(var_yz), intent(inout) :: output 
    type(var_yz), intent(in) :: input 

    if ( input%grid(2) /= output%grid(2) ) stop "(=)grid violation"
    if ( input%grid(3) /= output%grid(3) ) stop "(=)grid violation"

    linked_counter_yz( output%id ) = linked_counter_yz( output%id ) -1 

    if ( linked_counter_yz( output%id ) == 0 ) then 
       free_mask_yz( output%id ) = .true. 
    end if 

    output%id = input%id 

       linked_counter_yz( input%id ) = linked_counter_yz( input%id ) + 1 

    if( free_mask_yz( input%id )  ) then 
       free_mask_yz( input%id ) = .false.
    end if 

    call garbege_collect

  end subroutine data_data_equal_yz_yz

  subroutine data_data_equal_xyz_x(output, input)
    type(var_xyz), intent(inout) :: output 
    type(var_x), intent(in) :: input 

    if ( input%grid(1) /= output%grid(1) ) stop "(=)grid violation"

    do iz = lb_axis3, ub_axis3
      do iy = lb_axis2, ub_axis2
        do ix = lb_axis1, ub_axis1

        work_xyz(ix, iy, iz, output%id) & 
                      = work_x(ix, 1, 1, input%id)  

        end do
      end do
    end do

    call garbege_collect

  end subroutine data_data_equal_xyz_x

  subroutine data_data_equal_xyz_y(output, input)
    type(var_xyz), intent(inout) :: output 
    type(var_y), intent(in) :: input 

    if ( input%grid(2) /= output%grid(2) ) stop "(=)grid violation"

    do iz = lb_axis3, ub_axis3
      do iy = lb_axis2, ub_axis2
        do ix = lb_axis1, ub_axis1

        work_xyz(ix, iy, iz, output%id) & 
                      = work_y(1, iy, 1, input%id)  

        end do
      end do
    end do

    call garbege_collect

  end subroutine data_data_equal_xyz_y

  subroutine data_data_equal_xyz_z(output, input)
    type(var_xyz), intent(inout) :: output 
    type(var_z), intent(in) :: input 

    if ( input%grid(3) /= output%grid(3) ) stop "(=)grid violation"

    do iz = lb_axis3, ub_axis3
      do iy = lb_axis2, ub_axis2
        do ix = lb_axis1, ub_axis1

        work_xyz(ix, iy, iz, output%id) & 
                      = work_z(1, 1, iz, input%id)  

        end do
      end do
    end do

    call garbege_collect

  end subroutine data_data_equal_xyz_z

  subroutine data_data_equal_xyz_xy(output, input)
    type(var_xyz), intent(inout) :: output 
    type(var_xy), intent(in) :: input 

    if ( input%grid(1) /= output%grid(1) ) stop "(=)grid violation"
    if ( input%grid(2) /= output%grid(2) ) stop "(=)grid violation"

    do iz = lb_axis3, ub_axis3
      do iy = lb_axis2, ub_axis2
        do ix = lb_axis1, ub_axis1

        work_xyz(ix, iy, iz, output%id) & 
                      = work_xy(ix, iy, 1, input%id)  

        end do
      end do
    end do

    call garbege_collect

  end subroutine data_data_equal_xyz_xy

  subroutine data_data_equal_xyz_xz(output, input)
    type(var_xyz), intent(inout) :: output 
    type(var_xz), intent(in) :: input 

    if ( input%grid(1) /= output%grid(1) ) stop "(=)grid violation"
    if ( input%grid(3) /= output%grid(3) ) stop "(=)grid violation"

    do iz = lb_axis3, ub_axis3
      do iy = lb_axis2, ub_axis2
        do ix = lb_axis1, ub_axis1

        work_xyz(ix, iy, iz, output%id) & 
                      = work_xz(ix, 1, iz, input%id)  

        end do
      end do
    end do

    call garbege_collect

  end subroutine data_data_equal_xyz_xz

  subroutine data_data_equal_xyz_yz(output, input)
    type(var_xyz), intent(inout) :: output 
    type(var_yz), intent(in) :: input 

    if ( input%grid(2) /= output%grid(2) ) stop "(=)grid violation"
    if ( input%grid(3) /= output%grid(3) ) stop "(=)grid violation"

    do iz = lb_axis3, ub_axis3
      do iy = lb_axis2, ub_axis2
        do ix = lb_axis1, ub_axis1

        work_xyz(ix, iy, iz, output%id) & 
                      = work_yz(1, iy, iz, input%id)  

        end do
      end do
    end do

    call garbege_collect

  end subroutine data_data_equal_xyz_yz

  subroutine data_data_equal_xyz_xyz(output, input)
    type(var_xyz), intent(inout) :: output 
    type(var_xyz), intent(in) :: input 

    if ( input%grid(1) /= output%grid(1) ) stop "(=)grid violation"
    if ( input%grid(2) /= output%grid(2) ) stop "(=)grid violation"
    if ( input%grid(3) /= output%grid(3) ) stop "(=)grid violation"

    linked_counter_xyz( output%id ) = linked_counter_xyz( output%id ) -1 

    if ( linked_counter_xyz( output%id ) == 0 ) then 
       free_mask_xyz( output%id ) = .true. 
    end if 

    output%id = input%id 

       linked_counter_xyz( input%id ) = linked_counter_xyz( input%id ) + 1 

    if( free_mask_xyz( input%id )  ) then 
       free_mask_xyz( input%id ) = .false.
    end if 

    call garbege_collect

  end subroutine data_data_equal_xyz_xyz

end module gms_assign
