! ****************************************************************************** !
!> M U S U B I
!! The lattice Boltzmann solver within the APES suite
!! (c) 2012 German Research School for Simulation Sciences GmbH
!! (c) 2013 University of Siegen.
!!
!! For a documentation, run ./waf gendoxy and find the documentation at
!! ./Documentation/html/index.html
program musubi
  ! include treelm modules
  use mpi
  use tem_general_module,           only: tem_start, tem_finalize
  use tem_adaptation_config_module, only: tem_adapt_type

  ! include musubi modules
  ! RESPECT THE ORDER !!!!!!!!
  use mus_aux_module,                only: mus_banner
  use mus_config_module,             only: mus_load_config
  use mus_scheme_type_module,        only: mus_scheme_type
  use mus_param_module,              only: mus_param_type
  use mus_timer_module,              only: mus_init_mainTimer,  &
    &                                      mus_init_levelTimer, &
    &                                      mus_init_bcTimer
  use mus_geom_module,               only: mus_geom_type
  ! ESPECIALLY OF THE FOLLOWING MODULES
  use mus_control_module,            only: mus_control_type
  use mus_program_module,            only: mus_initialize, mus_solve, &
    &                                      mus_finalize
  use mus_varSys_module,             only: mus_varSys_solverData_type

  implicit none
  ! -----------------------------------------------------------------------------
  !> scheme types
  type(mus_scheme_type),            target :: scheme
  type(mus_geom_type),              target :: geometry
  type(mus_param_type),             target :: params
  type(mus_varSys_solverData_type), target :: solverData
  type(mus_control_type)                   :: control
  type(tem_adapt_type)                     :: adapt
  integer :: ierr
  ! -----------------------------------------------------------------------------

  ! Initialize environment
  call tem_start(codeName   = 'Musubi',                 &
    &            version    = params%version,           &
    &            general    = params%general,           &
    &            simControl = params%general%simControl )

  if (params%general%proc%rank == 0) then
    call mus_banner(solver = params%general%solver)
  end if

  call mus_init_mainTimer()

  ! load configuration file
  call mus_load_config( scheme     = scheme,     &
    &                   solverData = solverData, &
    &                   geometry   = geometry,   &
    &                   params     = params,     &
    &                   adapt      = adapt       )
      
  ! KM: Do not move this init_levelTimer and init_bcTimer from here,
  ! Need to be here for apesmate
  call mus_init_levelTimer( geometry%tree%global%minLevel, &
    &                       geometry%tree%global%maxLevel )
  call mus_init_bcTimer( geometry%boundary%nBCtypes )

  ! initialize musubi
  call mus_initialize( scheme     = scheme,     &
    &                  solverData = solverData, &
    &                  geometry   = geometry,   &
    &                  params     = params,     &
    &                  control    = control     )
  
  call mpi_barrier( MPI_COMM_WORLD, ierr )

  ! do main loop
  call mus_solve( scheme     = scheme,     &
    &             solverData = solverData, &
    &             geometry   = geometry,   &
    &             params     = params,     &
    &             control    = control,    &
    &             adapt      = adapt       )
  
  ! finialize musubi
  call mus_finalize( scheme       = scheme,                 &
    &                params       = params,                 &
    &                tree         = geometry%tree,          &
    &                nBCs         = geometry%boundary%nBCtypes, &
    &                levelPointer = geometry%levelPointer  )
  
  ! finalize treelm function like print run time info and mpi
  call tem_finalize(params%general)
      
end program musubi
