SUBROUTINE stepon
  !   Advance one time step, (num_step=4 for Runge Kutta 4 scheme)
  USE advance_field_routine, ONLY: advance_time_level, advance_field, advance_moments
  USE array , ONLY: moments_rhs_e, moments_rhs_i, Sepj, Sipj
  USE basic
  USE closure
  USE collision, ONLY : compute_TColl
  USE fields, ONLY: moments_e, moments_i, phi
  USE initial_par, ONLY: ACT_ON_MODES
  USE ghosts
  USE grid
  USE model, ONLY : LINEARITY, KIN_E
  use prec_const
  USE time_integration
  USE numerics, ONLY: play_with_modes
  USE processing, ONLY: compute_nadiab_moments
  USE utility, ONLY: checkfield

  IMPLICIT NONE

  INTEGER :: num_step
  LOGICAL :: mlend

   DO num_step=1,ntimelevel ! eg RK4 compute successively k1, k2, k3, k4
   !----- BEFORE: All fields are updated for step = n
      ! Compute right hand side from current fields
      ! N_rhs(N_n, nadia_n, phi_n, S_n, Tcoll_n)
      IF(KIN_E) CALL moments_eq_rhs_e
      CALL moments_eq_rhs_i
      ! ---- step n -> n+1 transition
      ! Advance from updatetlevel to updatetlevel+1 (according to num. scheme)
      CALL advance_time_level
      ! Update moments with the hierarchy RHS (step by step)
      ! N_n+1 = N_n + N_rhs(n)
      CALL advance_moments
      ! Closure enforcement of N_n+1
      CALL apply_closure_model
      ! Exchanges the ghosts values of N_n+1
      CALL update_ghosts
      ! Update collision C_n+1 = C(N_n+1)
      CALL compute_TColl
      ! Update electrostatic potential phi_n = phi(N_n+1)
      CALL poisson
      ! Update non adiabatic moments n -> n+1
      CALL compute_nadiab_moments
      ! Update nonlinear term S_n -> S_n+1(phi_n+1,N_n+1)
      CALL compute_Sapj
      ! Store or cancel/maintain zonal modes artificially
      CALL play_with_modes
      !-  Check before next step
      CALL checkfield_all()
      IF( nlend ) EXIT ! exit do loop

      CALL MPI_BARRIER(MPI_COMM_WORLD,ierr)
   !----- AFTER: All fields are updated for step = n+1
   END DO

   CONTAINS

      SUBROUTINE checkfield_all ! Check all the fields for inf or nan
        ! Execution time start
        CALL cpu_time(t0_checkfield)

        IF(LINEARITY .NE. 'linear') CALL anti_aliasing   ! ensure 0 mode for 2/3 rule
        IF(LINEARITY .NE. 'linear') CALL enforce_symmetry ! Enforcing symmetry on kx = 0

        mlend=.FALSE.
        IF(.NOT.nlend) THEN
           mlend=mlend .or. checkfield(phi,' phi')
           IF(KIN_E) THEN
           DO ip=ips_e,ipe_e
             DO ij=ijs_e,ije_e
              mlend=mlend .or. checkfield(moments_e(ip,ij,:,:,:,updatetlevel),' moments_e')
             ENDDO
           ENDDO
           ENDIF
           DO ip=ips_i,ipe_i
             DO ij=ijs_i,ije_i
              mlend=mlend .or. checkfield(moments_i(ip,ij,:,:,:,updatetlevel),' moments_i')
             ENDDO
           ENDDO
           CALL MPI_ALLREDUCE(mlend, nlend, 1, MPI_LOGICAL, MPI_LOR, MPI_COMM_WORLD, ierr)
        ENDIF

        ! Execution time end
        CALL cpu_time(t1_checkfield)
        tc_checkfield = tc_checkfield + (t1_checkfield - t0_checkfield)
      END SUBROUTINE checkfield_all

      SUBROUTINE anti_aliasing
        IF(KIN_E)THEN
        DO ip=ips_e,ipe_e
          DO ij=ijs_e,ije_e
            DO ikx=ikxs,ikxe
              DO iky=ikys,ikye
                DO iz=izs,ize
                  moments_e( ip,ij,ikx,iky,iz,:) = AA_x(ikx)* AA_y(iky) * moments_e( ip,ij,ikx,iky,iz,:)
                END DO
              END DO
            END DO
          END DO
        END DO
        ENDIF
        DO ip=ips_i,ipe_i
          DO ij=ijs_i,ije_i
            DO ikx=ikxs,ikxe
              DO iky=ikys,ikye
                DO iz=izs,ize
                  moments_i( ip,ij,ikx,iky,iz,:) = AA_x(ikx)* AA_y(iky) * moments_i( ip,ij,ikx,iky,iz,:)
                END DO
              END DO
            END DO
          END DO
        END DO
      END SUBROUTINE anti_aliasing

      SUBROUTINE enforce_symmetry ! Force X(k) = X(N-k)* complex conjugate symmetry
        IF ( contains_kx0 ) THEN
          ! Electron moments
          IF(KIN_E) THEN
          DO ip=ips_e,ipe_e
            DO ij=ijs_e,ije_e
              DO iz=izs,ize
                DO iky=2,Nky/2 !symmetry at kx = 0
                  moments_e( ip,ij,ikx_0,iky,iz, :) = CONJG(moments_e( ip,ij,ikx_0,Nky+2-iky,iz, :))
                END DO
                ! must be real at origin
                moments_e(ip,ij, ikx_0,iky_0,iz, :) = REAL(moments_e(ip,ij, ikx_0,iky_0,iz, :))
              END DO
            END DO
          END DO
          ENDIF
          ! Ion moments
          DO ip=ips_i,ipe_i
            DO ij=ijs_i,ije_i
              DO iz=izs,ize
                DO iky=2,Nky/2 !symmetry at kx = 0
                  moments_i( ip,ij,ikx_0,iky,iz, :) = CONJG(moments_i( ip,ij,ikx_0,Nky+2-iky,iz, :))
                END DO
                ! must be real at origin and top right
                moments_i(ip,ij, ikx_0,iky_0,iz, :) = REAL(moments_i(ip,ij, ikx_0,iky_0,iz, :))
              END DO
            END DO
          END DO
          ! Phi
          DO iky=2,Nky/2 !symmetry at kx = 0
            phi(ikx_0,iky,:) = phi(ikx_0,Nky+2-iky,:)
          END DO
          ! must be real at origin
          phi(ikx_0,iky_0,:) = REAL(phi(ikx_0,iky_0,:))
        ENDIF
      END SUBROUTINE enforce_symmetry

END SUBROUTINE stepon