#define ESMF_ERR_ABORT(rc) if (ESMF_LogFoundError(rc, msg="Aborting NMMB", line=__LINE__, file=__FILE__)) call ESMF_Finalize(endflag=ESMF_END_ABORT)

program nmmb

  use mpi
  use esmf
  use module_nmm_grid_comp ,only: nmm_register

  implicit none

  integer :: RC, RC_USER
  integer :: MYPE
  integer :: YY,MM,DD,HH,MNS,SEC, NHOURS_FCST
  type(ESMF_TimeInterval) :: RUNDURATION,TIMESTEP
  type(ESMF_Time) :: STARTTIME

  type(ESMF_VM) :: VM
  type(ESMF_Config) :: CF_MAIN
  type(ESMF_GridComp) :: NMM_GC
  type(ESMF_State) :: NMM_ES,NMM_IS
  type(ESMF_Clock) :: CLOCK

#ifdef ENABLE_SMP
  integer, external :: OMP_GET_NUM_THREADS, OMP_GET_THREAD_NUM
#endif

#ifdef ENABLE_SMP
!$omp parallel
  write(0,'(A,I0,A,I0,A,I0)')"Number of OMP threads ",OMP_GET_NUM_THREADS(),". This is thread number ",OMP_GET_THREAD_NUM()
!$omp end parallel
#endif

  call ESMF_Initialize(VM=VM,defaultCalKind=ESMF_CALKIND_GREGORIAN,logkindflag=ESMF_LOGKIND_MULTI,rc=RC); ESMF_ERR_ABORT(RC)
  call ESMF_VMGet(vm=VM,localpet=MYPE,rc=RC); ESMF_ERR_ABORT(RC)

! call redirect(mype)

  CF_MAIN = ESMF_ConfigCreate(rc=RC)
  call ESMF_ConfigLoadFile(config=CF_MAIN,filename='configure_file_01',rc=RC); ESMF_ERR_ABORT(RC)

  call ESMF_TimeIntervalSet(timeinterval=TIMESTEP,s=1,sn=0,sd=1,rc=RC); ESMF_ERR_ABORT(RC)

  call ESMF_ConfigGetAttribute(config=CF_MAIN,value =YY,label='start_year:',rc=RC); ESMF_ERR_ABORT(RC)
  call ESMF_ConfigGetAttribute(config=CF_MAIN,value =MM,label='start_month:',rc=RC); ESMF_ERR_ABORT(RC)
  call ESMF_ConfigGetAttribute(config=CF_MAIN,value =DD,label='start_day:',rc=RC); ESMF_ERR_ABORT(RC)
  call ESMF_ConfigGetAttribute(config=CF_MAIN,value =HH,label='start_hour:',rc=RC); ESMF_ERR_ABORT(RC)
  call ESMF_ConfigGetAttribute(config=CF_MAIN,value =MNS,label='start_minute:',rc=RC); ESMF_ERR_ABORT(RC)
  call ESMF_ConfigGetAttribute(config=CF_MAIN,value =SEC,label='start_second:',rc=RC); ESMF_ERR_ABORT(RC)
  call ESMF_TimeSet(time=STARTTIME,yy=YY,mm=MM,dd=DD,h=HH,m=MNS,s=SEC,rc=RC); ESMF_ERR_ABORT(RC)

  call ESMF_ConfigGetAttribute(config=CF_MAIN,value=NHOURS_FCST,label='nhours_fcst:',rc=RC); ESMF_ERR_ABORT(RC)
  call ESMF_TimeIntervalSet(timeinterval=RUNDURATION,s=NHOURS_FCST*3600,rc=RC); ESMF_ERR_ABORT(RC)

  CLOCK = ESMF_ClockCreate(name='CLOCK',timeStep=TIMESTEP,startTime=STARTTIME,runDuration=RUNDURATION,rc=RC); ESMF_ERR_ABORT(RC)

  NMM_GC = ESMF_GridCompCreate(name='NMMB Grid Comp',config=CF_MAIN,rc=RC); ESMF_ERR_ABORT(RC)
  call ESMF_GridCompSetServices(NMM_GC,NMM_REGISTER,rc=RC); ESMF_ERR_ABORT(RC)

  NMM_IS = ESMF_StateCreate(name='NMMB Import State',rc=RC); ESMF_ERR_ABORT(RC)
  NMM_ES = ESMF_StateCreate(name='NMMB Export State',rc=RC); ESMF_ERR_ABORT(RC)

  call ESMF_GridCompInitialize (gridcomp=NMM_GC,importState=NMM_IS,exportState=NMM_ES,clock=CLOCK,phase=1,userRc=RC_USER,rc=RC)
  ESMF_ERR_ABORT(RC)
  ESMF_ERR_ABORT(RC_USER)

  call ESMF_GridCompRun        (gridcomp=NMM_GC,importState=NMM_IS,exportState=NMM_ES,clock=CLOCK,phase=1,userRc=RC_USER,rc=RC)
  ESMF_ERR_ABORT(RC)
  ESMF_ERR_ABORT(RC_USER)

  call ESMF_GridCompFinalize   (gridcomp=NMM_GC,importState=NMM_IS,exportState=NMM_ES,clock=CLOCK,phase=1,userRc=RC_USER,rc=RC)
  ESMF_ERR_ABORT(RC)
  ESMF_ERR_ABORT(RC_USER)

  call ESMF_ClockDestroy(clock=CLOCK,rc=RC); ESMF_ERR_ABORT(RC)
  call ESMF_StateDestroy(state=NMM_IS,rc=RC); ESMF_ERR_ABORT(RC)
  call ESMF_StateDestroy(state=NMM_ES,rc=RC); ESMF_ERR_ABORT(RC)
  call ESMF_GridCompDestroy(gridcomp=NMM_GC,rc=RC); ESMF_ERR_ABORT(RC)

  call ESMF_Finalize(endflag=ESMF_END_KEEPMPI,rc=RC); ESMF_ERR_ABORT(RC)

  call MPI_Barrier(MPI_COMM_WORLD, RC); ESMF_ERR_ABORT(RC)
  call MPI_Finalize(RC); ESMF_ERR_ABORT(RC)

  if (MYPE == 0) then
    write(*,*)"Execution of NMMB finished successfully!"
    write(0,*)"Execution of NMMB finished successfully!"
  end if

end program nmmb
