MODULE etat0_start_file_mod

CONTAINS

   SUBROUTINE init_etat0
      USE getin_mod, only: getin
      USE xios_mod
      USE omp_para
      USE time_mod
      USE restart_mod
      USE output_field_mod, only: xios_output
      IMPLICIT NONE

      IF (using_xios) THEN
         xios_output = .TRUE.
         CALL getin('xios_output', xios_output)
      ELSE
         xios_output = .FALSE.
      END IF
      IF (using_xios .AND. .NOT. xios_output) THEN
         STOP "Reading initial conditions from the start file (etat0=start_file) requires turned on XIOS (xios_output=TRUE)"
      END IF

      IF (is_omp_master) THEN
         IF (using_xios) THEN
            CALL xios_set_file_attr("start", enabled=.TRUE., mode="read", output_freq=(itaumax + 1)*xios_timestep)
         END IF
      END IF

      CALL set_write_start(.FALSE.)
      CALL set_read_start(.TRUE.)

   END SUBROUTINE init_etat0

   SUBROUTINE etat0(f_ps, f_phis, f_theta_rhodz, f_u, f_q)
      USE icosa
      USE restart_mod
      USE wind_from_lonlat_mod, ONLY: ulonlat2un
      USE wind_to_lonlat_mod, ONLY: un2ulonlat
      USE write_field_mod
      USE time_mod
      USE transfert_mod
      USE omp_para
      USE checksum_mod
      IMPLICIT NONE
      TYPE(t_field), POINTER :: f_ps(:)
      TYPE(t_field), POINTER :: f_phis(:)
      TYPE(t_field), POINTER :: f_theta_rhodz(:)
      TYPE(t_field), POINTER :: f_u(:)
      TYPE(t_field), POINTER :: f_q(:)

      TYPE(t_field), POINTER, SAVE :: f_ulon(:)
      TYPE(t_field), POINTER, SAVE :: f_ulat(:)
      TYPE(t_field), POINTER, SAVE :: f_theta_rhodz_1d(:)
      REAL(rstd), POINTER :: theta_rhodz(:, :, :), theta_rhodz_1d(:, :)

      LOGICAL :: etat0_start_file_colocated = .FALSE.
      INTEGER :: ind
      LOGICAL :: raz

      ! @getin_doc etat0_start_file_colocated realm=initial type=logical default=.FALSE.
      ! Effective only when `etat0==start_file`.
      ! If this flag is set to .FALSE., C-grid winds are read from the start file. This allows
      ! a perfect restart but works only if restarting from a run using the exact same mesh.
      ! Set this flag to .TRUE. when restarting from a restart file produced by a previous
      ! run on a different mesh. In that case, zonal and meridional winds at cell centers,
      ! interpolated by XIOS from the previous mesh, are read.
      CALL getin("etat0_start_file_colocated", etat0_start_file_colocated)
      CALL allocate_field(f_theta_rhodz_1d, field_t, type_real, llm, name='theta_rhodz')

!$OMP BARRIER
      DO ind = 1, ndomain
         IF (.NOT. assigned_domain(ind) .OR. .NOT. is_omp_level_master) CYCLE
         f_q(ind)%rval4d(:, :, :) = 0.
      END DO
!$OMP BARRIER
      CALL checksum(f_q)
      IF (.NOT. etat0_start_file_colocated) THEN
         CALL allocate_field(f_ulon, field_t, type_real, llm, name='ulon')
         CALL allocate_field(f_ulat, field_t, type_real, llm, name='ulat')
         CALL read_start_fields(itau0, f_ps, f_phis, f_theta_rhodz_1d, f_u, f_q)
         CALL transfert_request(f_ps, req_i1)
         CALL transfert_request(f_ps, req_i0)
         CALL transfert_request(f_phis, req_i1)
         CALL transfert_request(f_phis, req_i0)
         CALL transfert_request(f_theta_rhodz_1d, req_i1)
         CALL transfert_request(f_theta_rhodz_1d, req_i0)
         CALL transfert_request(f_q, req_i1)
         CALL transfert_request(f_q, req_i0)
         CALL transfert_request(f_u, req_e1_vect)
         CALL transfert_request(f_u, req_e0_vect)
         CALL un2ulonlat(f_u, f_ulon, f_ulat)

         CALL deallocate_field(f_ulon)
         CALL deallocate_field(f_ulat)

      ELSE
         CALL allocate_field(f_ulon, field_t, type_real, llm, name='ulon')
         CALL allocate_field(f_ulat, field_t, type_real, llm, name='ulat')
         CALL read_start_fields(itau0, f_ps, f_phis, f_theta_rhodz_1d, f_ulon, f_ulat, f_q)
         CALL transfert_request(f_ulat, req_i1)
         CALL transfert_request(f_ulat, req_i0)
         CALL transfert_request(f_ulon, req_i1)
         CALL transfert_request(f_ulon, req_i0)

         CALL ulonlat2un(f_ulon, f_ulat, f_u)

         CALL transfert_request(f_ps, req_i1)
         CALL transfert_request(f_ps, req_i0)
         CALL transfert_request(f_phis, req_i1)
         CALL transfert_request(f_phis, req_i0)
         CALL transfert_request(f_theta_rhodz_1d, req_i1)
         CALL transfert_request(f_theta_rhodz_1d, req_i0)
         CALL transfert_request(f_q, req_i1)
         CALL transfert_request(f_q, req_i0)
         CALL transfert_request(f_u, req_e1_vect)
         CALL transfert_request(f_u, req_e0_vect)

         CALL deallocate_field(f_ulon)
         CALL deallocate_field(f_ulat)
      END IF

!$OMP BARRIER
      DO ind = 1, ndomain
         IF (.NOT. assigned_domain(ind) .OR. .NOT. is_omp_level_master) CYCLE
         theta_rhodz = f_theta_rhodz(ind); theta_rhodz_1d = f_theta_rhodz_1d(ind)
         theta_rhodz(:, :, 1) = theta_rhodz_1d(:, :)
      END DO
!$OMP BARRIER

      CALL bcast(itau0)

      ! @getin_doc etat0_start_iteration_reset realm=initial type=logical default=.FALSE.
      !  If `.TRUE.`, sets to zero the *default* value of the iteration counter at the beginning of the time loop.
      ! See `etat0_start_iteration`.
      raz = .FALSE.
      CALL getin("etat0_start_iteration_reset", raz)

      ! @getin_doc etat0_start_iteration realm=initial type=integer
      !  Value of iteration counter at the beginning of the time loop.
      ! The default value is :
      ! * read from the restart file if `etat0=="start_file"` or `etat0=="start_file_interp"`
      ! * zero otherwise
      ! * forced to zero if `etat0_start_iteration_reset==.TRUE.`
      IF (raz) itau0 = 0
      CALL getin("etat0_start_iteration", itau0)

   END SUBROUTINE etat0

END MODULE etat0_start_file_mod
