!------------------------------------------------------------------------------
!        IST/MARETEC, Water Modelling Group, Mohid modelling system
!------------------------------------------------------------------------------
!
! TITLE         : Mohid Model
! PROJECT       : Water
! PROGRAM       : MohidWater
! URL           : http://www.mohid.com
! AFFILIATION   : IST/MARETEC, Marine Modelling Group
! DATE          : May 2003
! REVISION      : Frank Braunschweig - v4.0
! DESCRIPTION   : Main Program which run Mohid Water
!
!------------------------------------------------------------------------------
!            
! Modelling system Mohid a general description
!              MOHID is a full 3D-baroclinic model and has been developed 
!              using an object oriented programming philosophy and using all 
!              the FORTRAN 95 potential. The system has two main classes: the 
!              first one manages the hydrodynamic properties (e.g. velocity, 
!              elevation, water fluxes, turbulent viscosity) and the second 
!              one the water properties (e.g. salinity, temperature, density, 
!              SPM, nutrients, phytoplankton, coliforms). The model is based 
!              on a finite volume concept. In this approach the discrete form 
!              of the governing equations are applied macroscopically to the 
!              cell control volume in the form of flux divergence. As a consequence 
!              this method automatically guarantees the conservation of transported 
!              properties .
!              The model computes the evolution of several flow and water properties
!              in a finite-volume.
! For further information please take a look at:
!              http://www.mohid.com
! or contact
!              e-mail: general@mohid.com
!
!


program MohidWater

    use ModuleGlobalData
    use ModuleTime
    use ModuleEnterData,        only : ReadFileName 
    use ModuleStopWatch,        only : CreateWatchGroup, KillWatchGroup
    use ModuleHorizontalGrid,   only : ConstructHorizontalGrid,                          &
                                       ConstructFatherGridLocation,                      &
                                       GetGridFileName
    use ModuleModel,            only : ConstructModel, UpdateTimeAndMapping,             &
                                       RunModel, KillModel, GetModelTimeStep,            &
                                       GetModelTimeLimits,  GetModelInstanceIDs,         &
                                       GetModelCurrentTime
#ifdef _USE_MPI
    use ModuleHydrodynamic,     only : GetHydroNeedsFather, SetHydroFather,              &
                                       SendHydrodynamicMPI, RecvHydrodynamicMPI,         &
                                       UpdateHydroMPI
    use ModuleWaterproperties,  only : GetWaterNeedsFather, GetPropListNeedsFather,      &
                                       SetWaterPropFather, SendWaterPropertiesMPI,       &
                                       RecvWaterPropertiesMPI, UpdateWaterMPI
    use ModuleFunctions,        only : MPIKind
#else
    use ModuleHydrodynamic,     only : GetHydroNeedsFather, SetHydroFather
    use ModuleWaterproperties,  only : GetWaterNeedsFather, GetPropListNeedsFather,      &
                                       SetWaterPropFather
#endif
    

    implicit none


    type T_ModelLink
        logical                                             :: Hydro   = .false.
        logical                                             :: Water   = .false.
        integer                                             :: nProp
        integer, dimension(:), pointer                      :: PropertyIDNumbers
        type (T_Size2D)                                     :: Window
    end type 


    type T_MohidWater
        integer                                             :: ModelID
        integer                                             :: ModelLevel
        character(PathLength)                               :: ModelName
        integer                                             :: HorizontalGridID
        integer                                             :: HydrodynamicID
        integer                                             :: WaterpropertiesID
        type (T_Time)                                       :: CurrentTime
        type (T_Time)                                       :: InfoTime         !Time of the last father information
        logical                                             :: SubOn
        integer                                             :: nSubModels
        type (T_ModelLink)                                  :: FatherLink
        type (T_ModelLink), dimension(:), pointer           :: SubmodelLink
        integer                                             :: MPI_ID
        integer, dimension(:), pointer                      :: SubMPIID
        integer                                             :: FatherGridID  = 0    !MPI only
        type (T_MohidWater), pointer                        :: FatherModel
        type (T_MohidWater), pointer                        :: Next    
    end type T_MohidWater


    !Variables
    type (T_MohidWater), pointer                            :: FirstModel
    type(T_Time)                                            :: GlobalBeginTime
    type(T_Time)                                            :: GlobalEndTime
    type(T_Time)                                            :: GlobalCurrentTime

    !MPI Stuff        
    integer                                                 :: myMPI_ID = null_int
    integer                                                 :: nMPI_Processes

#ifdef _USE_MPI
    include "mpif.f90"
    character(MPI_MAX_PROCESSOR_NAME)                       :: myMPI_Processor
    integer                                                 :: Precision
#else
    character(StringLength)                                 :: myMPI_Processor
#endif

    logical                                                 :: RunInParallel
                                                            
    !CPU / System Time
    type (T_Time)                                           :: InitialSystemTime, FinalSystemTime
    real                                                    :: TotalCPUTime,     ElapsedSeconds

    real                                                    :: CPUTimeConstructor, CPUTimeModifier
    real                                                    :: WorkCycleElapsed, WorkCycleCPUTime
    type (T_Time)                                           :: WorkCycleInitial, WorkCycleFinal


#ifdef _USE_MPI
    RunInParallel = .true.
#else
    RunInParallel = .false.

    !Disable unused variable warnings
    myMPI_Processor = 'My Processor'
#endif
    
    if (RunInParallel) then
        call ConstructMohidWaterMPI
    else
        call ConstructMohidWater
    endif

    call ModifyMohidWater

    if (RunInParallel) then
        call KillMohidWaterMPI
    else
        call KillMohidWater
    endif


    contains
    
    !--------------------------------------------------------------------------

    subroutine ConstructMohidWater

        !Arguments-------------------------------------------------------------

        !Local-----------------------------------------------------------------
        integer                                     :: STAT_CALL
        character(PathLength)                       :: WatchFile, DTLogFile
        type (T_MohidWater), pointer                :: CurrentModel
        integer                                     :: iProp

        !Common Startup tasks
        call StartUpMohid   ("Mohid Water")
        call GetSystemTime  (InitialSystemTime)

        !Monitor Performance of the model execution?
        call ReadFileName('OUTWATCH', WatchFile, Message = 'Stop Watch File', STAT = STAT_CALL)
        if (STAT_CALL == SUCCESS_) then
            STAT_CALL   = CreateWatchGroup (WatchFile)
            MonitorPerformance  = .true.
        else
            MonitorPerformance  = .false.
        endif

        !Monitors DT
        call ReadFileName('DT_LOG', DTLogFile, Message = 'Start DTLog File', STAT = STAT_CALL)
        if (STAT_CALL == SUCCESS_) then            
            MonitorDT  = .true.
        else
            MonitorDT  = .false.
        endif

        if (MonitorDT) then
            call UnitsManager (UnitDT, OPEN_FILE)      
            open(UNIT   = UnitDT, FILE   = DTLogFile, STATUS  = "UNKNOWN", IOSTAT  = STAT_CALL)
            if (STAT_CALL /= SUCCESS_) stop 'ConstructMohidWater - MohidWater - ERR01'
        end if

        !Constucts the list of the model
        call ConstructModelList

        !Constructs the Models
        CurrentModel => FirstModel
        do while (associated(CurrentModel))

            call SetFilesName  (CurrentModel%ModelName)
            call ConstructModel(CurrentModel%ModelID, CurrentModel%ModelName, STAT = STAT_CALL)
            if (STAT_CALL /= SUCCESS_) stop 'ConstructMohidWater - MohidWater - ERR02'

            !Get the Instance IDs of the Objects which are necessary for Model/SubModel
            !comunication
            call GetModelInstanceIDs      (CurrentModel%ModelID,                              &
                                           HorizontalGridID  = CurrentModel%HorizontalGridID, &
                                           HydrodynamicID    = CurrentModel%HydrodynamicID,   &
                                           WaterpropertiesID = CurrentModel%WaterpropertiesID,&
                                           STAT = STAT_CALL)
            if (STAT_CALL /= SUCCESS_) stop 'ConstructMohidWater - MohidWater - ERR03'

            !Gets Current Time of the model
            call GetModelCurrentTime      (CurrentModel%ModelID, CurrentModel%CurrentTime,    &
                                           STAT = STAT_CALL)
            if (STAT_CALL /= SUCCESS_) stop 'ConstructMohidWater - MohidWater - ERR04'

            CurrentModel => CurrentModel%Next
        enddo

        !Checks the limits of the model (always model one which controls it)
        call GetModelTimeLimits (FirstModel%ModelID, GlobalBeginTime, GlobalEndTime, STAT = STAT_CALL)
        if (STAT_CALL /= SUCCESS_) stop 'ConstructMohidWater - MohidWater - ERR05'


        !Construct the Father Grid
        CurrentModel => FirstModel
        do while (associated(CurrentModel))
            if (associated(CurrentModel%FatherModel)) then

                call ConstructFatherGridLocation(CurrentModel%HorizontalGridID,             &
                                                 CurrentModel%FatherModel%HorizontalGridID, &
                                                 STAT = STAT_CALL)
                if (STAT_CALL /= SUCCESS_) stop 'ConstructMohidWater - MohidWater - ERR06'

            endif
            CurrentModel => CurrentModel%Next
        enddo

        !Verifies which Model needs Hydrodynamic / Waterproperties conditions from father
        CurrentModel => FirstModel
        do while (associated(CurrentModel))

            if (associated(CurrentModel%FatherModel)) then

                call GetHydroNeedsFather (CurrentModel%HydrodynamicID,                   &
                                          CurrentModel%FatherLink%Hydro,                 &
                                          STAT = STAT_CALL)
                if (STAT_CALL /= SUCCESS_) stop 'ConstructMohidWater - MohidWater - ERR07'


                call GetWaterNeedsFather (CurrentModel%WaterpropertiesID,                &
                                          CurrentModel%FatherLink%Water,                 &
                                          CurrentModel%FatherLink%nProp,                 &
                                          STAT = STAT_CALL)
                if (STAT_CALL /= SUCCESS_) stop 'ConstructMohidWater - MohidWater - ERR08'


                if (CurrentModel%FatherLink%Hydro) then
                    call SetHydroFather (CurrentModel%HydrodynamicID,                     &
                                         CurrentModel%FatherModel%HydrodynamicID,         &
                                         InitialField = .true., STAT = STAT_CALL)
                endif

                if (CurrentModel%FatherLink%Water) then

                    allocate (CurrentModel%FatherLink%PropertyIDNumbers(CurrentModel%FatherLink%nProp))
                    call GetPropListNeedsFather(CurrentModel%WaterPropertiesID,              &
                                                CurrentModel%FatherLink%PropertyIDNumbers,   &
                                                STAT = STAT_CALL)

                    do iProp = 1, CurrentModel%FatherLink%nProp

                        call SetWaterPropFather (CurrentModel%WaterPropertiesID,                    &
                                                 CurrentModel%FatherModel%WaterPropertiesID,        &
                                                 CurrentModel%FatherLink%PropertyIDNumbers(iProp),  &
                                                 InitialField= .true.,                              &
                                                 STAT = STAT_CALL)

                    enddo

                endif


            endif
            CurrentModel => CurrentModel%Next
        enddo

        !Gets System Time
        call GetSystemTime (WorkCycleInitial)
        call cpu_time      (CPUTimeConstructor)

    end subroutine ConstructMohidWater

    !--------------------------------------------------------------------------

    subroutine ConstructMohidWaterMPI

#ifdef _USE_MPI
        !Arguments-------------------------------------------------------------

        !Local-----------------------------------------------------------------
        integer                                     :: STAT_CALL
        character(PathLength)                       :: WatchFile, DTLogFile
        type (T_MohidWater), pointer                :: CurrentModel
        integer                                     :: tag = 0
        integer                                     :: status(MPI_STATUS_SIZE)
        integer                                     :: iSub, length, iProp
        character(PathLength)                       :: FileNameStr
        integer, dimension(PathLength)              :: FileNameInt
        real, dimension(6)                          :: AuxBeg, AuxEnd
        integer                                     :: iProc


        call MPI_INIT               (STAT_CALL )
        call MPI_COMM_RANK          (MPI_COMM_WORLD, myMPI_ID, STAT_CALL)
        call MPI_COMM_SIZE          (MPI_COMM_WORLD, nMPI_Processes, STAT_CALL)
        call MPI_GET_PROCESSOR_NAME (myMPI_Processor, length, STAT_CALL)
        call MPI_Barrier            (MPI_COMM_WORLD, STAT_CALL)

        !Reads the file Tree.dat and constructs the list of models
        !Like this every model has access to the whole model list
        !Do this sequentially, so there will be no conflict accessing Tree.dat
        do iProc = 0, nMPI_Processes - 1

            if (iProc == myMPI_ID) then

                !Common Startup tasks
                call StartUpMohid   ("Mohid Water on "//trim(adjustl(myMPI_Processor)))
                call GetSystemTime  (InitialSystemTime)
                call ConstructModelList

            endif

            !Wait for all processes
            call MPI_Barrier   (MPI_COMM_WORLD, STAT_CALL)
        enddo

        !Construct all modules. Each module is constructed one after the other. Between each 
        !construction, the other modules wait at MPI_Barrier below.
        CurrentModel => FirstModel
        do while (associated(CurrentModel))

            if (myMPI_ID == CurrentModel%MPI_ID) then

                call SetFilesName  (CurrentModel%ModelName)

                !Monitor Performance of the model execution?
                call ReadFileName('OUTWATCH', WatchFile, Message = 'Stop Watch File', STAT = STAT_CALL)
                if (STAT_CALL == SUCCESS_) then
                    STAT_CALL   = CreateWatchGroup (WatchFile)
                    MonitorPerformance  = .true.
                else
                    MonitorPerformance  = .false.
                endif

                !Monitors DT
                call ReadFileName('DT_LOG', DTLogFile, Message = 'Start DTLog File', STAT = STAT_CALL)
                if (STAT_CALL == SUCCESS_) then            
                    MonitorDT  = .true.
                else
                    MonitorDT  = .false.
                endif

                if (MonitorDT) then
                    call UnitsManager (UnitDT, OPEN_FILE)      
                    open(UNIT   = UnitDT, FILE   = DTLogFile, STATUS  = "UNKNOWN", IOSTAT  = STAT_CALL)
                    if (STAT_CALL /= SUCCESS_) stop 'ConstructMohidWaterMPI - MohidWater - ERR01'
                end if

                call ConstructModel(CurrentModel%ModelID, CurrentModel%ModelName, STAT = STAT_CALL)
            
                !Get the Instance IDs of the Objects which are necessary for Model/SubModel
                !comunication
                call GetModelInstanceIDs      (CurrentModel%ModelID,                              &
                                               HorizontalGridID  = CurrentModel%HorizontalGridID, &
                                               HydrodynamicID    = CurrentModel%HydrodynamicID,   &
                                               WaterpropertiesID = CurrentModel%WaterpropertiesID,&
                                               STAT = STAT_CALL)
                if (STAT_CALL /= SUCCESS_) stop 'ConstructMohidWaterMPI - MohidWater - ERR01'

                !Gets Current Time of the model
                call GetModelCurrentTime      (CurrentModel%ModelID, CurrentModel%CurrentTime,    &
                                               STAT = STAT_CALL)
                if (STAT_CALL /= SUCCESS_) stop 'ConstructMohidWaterMPI - MohidWater - ERR04'

                !Sets the last info time 
                CurrentModel%InfoTime = CurrentModel%CurrentTime

            endif

            CurrentModel => CurrentModel%Next

            !Waits for all processes
            call MPI_Barrier  (MPI_COMM_WORLD, STAT_CALL)

        enddo

        !Waits for all processes
        call MPI_Barrier  (MPI_COMM_WORLD, STAT_CALL)

        !Sends the information about the Grid to the submodels
        CurrentModel => FirstModel
        do while (associated(CurrentModel))

            !Send the information to the submodels
            if (CurrentModel%MPI_ID == myMPI_ID) then
                
                do iSub = 1, CurrentModel%nSubModels
                        
                    !Gets the name of the file
                    call GetGridFileName          (CurrentModel%HorizontalGridID, FileNameStr, STAT = STAT_CALL)
                    if (STAT_CALL /= SUCCESS_) stop 'ConstructMohidWaterMPI - MohidWater - ERR03'

                    !Converts a String to an integer Array
                    call ConvertStrToInt (FileNameStr, FileNameInt, PathLength)

                    !Send name to submodel
                    call MPI_Send (FileNameInt, PathLength, MPI_INTEGER,                 &
                                   CurrentModel%SubMPIID(iSub), tag, MPI_COMM_WORLD,     &
                                   STAT_CALL)
                    if (STAT_CALL /= SUCCESS_) stop 'ConstructMohidWaterMPI - MohidWater - ERR04'
                enddo


                if (associated(CurrentModel%FatherModel)) then

                    call MPI_Recv (FileNameInt, PathLength, MPI_INTEGER, CurrentModel%FatherModel%MPI_ID, &
                                   tag, MPI_COMM_WORLD, status, STAT_CALL)

                    !Converts an integer Array to a String
                    call ConvertIntToStr (FileNameInt, FileNameStr, PathLength)

                    !Constructs the Father Grid
                    call ConstructHorizontalGrid (HorizontalGridID = CurrentModel%FatherGridID, &
                                                  DataFile         = FileNameStr,               &
                                                  STAT             = STAT_CALL)
                    if (STAT_CALL /= SUCCESS_) stop 'ConstructModel - ModuleModel - ERR03'

                    !Constructs the location of the father grid
                    call ConstructFatherGridLocation(CurrentModel%HorizontalGridID,             &
                                                     CurrentModel%FatherGridID,                 &
                                                     Window = CurrentModel%FatherLink%Window,   &
                                                     STAT   = STAT_CALL)

                endif

            endif

            CurrentModel => CurrentModel%Next


        enddo  
             
        !Wait for all
        call MPI_Barrier  (MPI_COMM_WORLD, STAT_CALL)
           
        !Sends to all processes the information about GlobalBeginTime end GlobalEndTime
        if (myMPI_ID == 0) then

            !Checks the limits of the model (always model one which controls it)
            call GetModelTimeLimits (FirstModel%ModelID, GlobalBeginTime, GlobalEndTime, STAT = STAT_CALL)
            if (STAT_CALL /= SUCCESS_) stop 'ConstructMohidWater - MohidWater - ERR05'

            call ExtractDate (GlobalBeginTime, AuxBeg(1), AuxBeg(2), AuxBeg(3),          &
                              AuxBeg(4), AuxBeg(5), AuxBeg(6))

            call ExtractDate (GlobalEndTime,   AuxEnd(1), AuxEnd(2), AuxEnd(3),          &
                              AuxEnd(4), AuxEnd(5), AuxEnd(6))

        endif

        Precision = MPIKind(AuxBeg(1))

        call MPI_Bcast(AuxBeg, 6, Precision, 0, MPI_COMM_WORLD, STAT_CALL)
        call MPI_Bcast(AuxEnd, 6, Precision, 0, MPI_COMM_WORLD, STAT_CALL)

        if (myMPI_ID /= 0) then
            call SetDate (GlobalBeginTime, AuxBeg(1), AuxBeg(2), AuxBeg(3),              &
                          AuxBeg(4), AuxBeg(5), AuxBeg(6))

            call SetDate (GlobalEndTime, AuxEnd(1), AuxEnd(2), AuxEnd(3),                &
                          AuxEnd(4), AuxEnd(5), AuxEnd(6))
        endif

        !Wait for all
        call MPI_Barrier  (MPI_COMM_WORLD, STAT_CALL)

        !Fills in FatherLink
        CurrentModel => FirstModel
        do while (associated(CurrentModel))

            !Send the information to the submodels
            if (CurrentModel%MPI_ID == myMPI_ID) then

                if (associated(CurrentModel%FatherModel)) then

                    call GetHydroNeedsFather (CurrentModel%HydrodynamicID,               &
                                              CurrentModel%FatherLink%Hydro,             &
                                              STAT = STAT_CALL)
                    if (STAT_CALL /= SUCCESS_) stop 'ConstructMohidWater - MohidWater - ERR07'
                    

                    call GetWaterNeedsFather (CurrentModel%WaterpropertiesID,            &
                                              CurrentModel%FatherLink%Water,             &
                                              CurrentModel%FatherLink%nProp,             &
                                              STAT = STAT_CALL)
                    if (STAT_CALL /= SUCCESS_) stop 'ConstructMohidWater - MohidWater - ERR08'


                    if (CurrentModel%FatherLink%Water) then

                        allocate (CurrentModel%FatherLink%PropertyIDNumbers(CurrentModel%FatherLink%nProp))
                        call GetPropListNeedsFather(CurrentModel%WaterPropertiesID,                 &
                                                    CurrentModel%FatherLink%PropertyIDNumbers,      &
                                                    STAT = STAT_CALL)

                    endif
                endif

            endif

            CurrentModel => CurrentModel%Next

        enddo  

        !Waits for all processes
        call MPI_Barrier  (MPI_COMM_WORLD, STAT_CALL)

        !Fills in SubModelLink
        CurrentModel => FirstModel
        do while (associated(CurrentModel))

            !Send the information to the submodels
            if (CurrentModel%MPI_ID == myMPI_ID) then

                do iSub = 1, CurrentModel%nSubModels

                    !Recieves information if submodel needs 
                    call MPI_Recv (CurrentModel%SubmodelLink(iSub)%Hydro, 1, MPI_LOGICAL, &
                                   CurrentModel%SubMPIID(iSub), tag, MPI_COMM_WORLD,      &
                                   status, STAT_CALL)
                    if (STAT_CALL /= SUCCESS_) stop 'ConstructMohidWaterMPI - MohidWater - ERR04'

                    call MPI_Recv (CurrentModel%SubmodelLink(iSub)%Water, 1, MPI_LOGICAL, &
                                   CurrentModel%SubMPIID(iSub), tag, MPI_COMM_WORLD,      &
                                   status, STAT_CALL)
                    if (STAT_CALL /= SUCCESS_) stop 'ConstructMohidWaterMPI - MohidWater - ERR04'

                    call MPI_Recv (CurrentModel%SubmodelLink(iSub)%nProp, 1, MPI_INTEGER, &
                                   CurrentModel%SubMPIID(iSub), tag, MPI_COMM_WORLD,      &
                                   status, STAT_CALL)
                    if (STAT_CALL /= SUCCESS_) stop 'ConstructMohidWaterMPI - MohidWater - ERR04'

                    allocate (CurrentModel%SubmodelLink(iSub)%PropertyIDNumbers(CurrentModel%SubmodelLink(iSub)%nProp))

                    call MPI_Recv (CurrentModel%SubmodelLink(iSub)%PropertyIDNumbers,  &
                                   CurrentModel%SubmodelLink(iSub)%nProp, MPI_INTEGER, &
                                   CurrentModel%SubMPIID(iSub), tag, MPI_COMM_WORLD,    &
                                   status, STAT_CALL)
                    if (STAT_CALL /= SUCCESS_) stop 'ConstructMohidWaterMPI - MohidWater - ERR04'


                    call MPI_Recv (CurrentModel%SubmodelLink(iSub)%Window%ILB, 1,         &
                                   MPI_INTEGER, CurrentModel%SubMPIID(iSub), tag,         &
                                   MPI_COMM_WORLD, status, STAT_CALL)
                    call MPI_Recv (CurrentModel%SubmodelLink(iSub)%Window%IUB, 1,         &
                                   MPI_INTEGER, CurrentModel%SubMPIID(iSub), tag,         &
                                   MPI_COMM_WORLD, status, STAT_CALL)
                    call MPI_Recv (CurrentModel%SubmodelLink(iSub)%Window%JLB, 1,         &
                                   MPI_INTEGER, CurrentModel%SubMPIID(iSub), tag,         &
                                   MPI_COMM_WORLD, status, STAT_CALL)
                    call MPI_Recv (CurrentModel%SubmodelLink(iSub)%Window%JUB, 1,         &
                                   MPI_INTEGER, CurrentModel%SubMPIID(iSub), tag,         &
                                   MPI_COMM_WORLD, status, STAT_CALL)

                    

                enddo


                if (associated(CurrentModel%FatherModel)) then

                    !Send to father information about Father link
                    call MPI_Send (CurrentModel%FatherLink%Hydro, 1, MPI_LOGICAL,        &
                                   CurrentModel%FatherModel%MPI_ID, tag, MPI_COMM_WORLD, STAT_CALL)

                    call MPI_Send (CurrentModel%FatherLink%Water, 1, MPI_LOGICAL,        &
                                   CurrentModel%FatherModel%MPI_ID, tag, MPI_COMM_WORLD, STAT_CALL)
                    
                    call MPI_Send (CurrentModel%FatherLink%nProp, 1, MPI_INTEGER,        &
                                   CurrentModel%FatherModel%MPI_ID, tag, MPI_COMM_WORLD, STAT_CALL)
                    
                    call MPI_Send (CurrentModel%FatherLink%PropertyIDNumbers,            &
                                   CurrentModel%FatherLink%nProp, MPI_INTEGER,           & 
                                   CurrentModel%FatherModel%MPI_ID, tag, MPI_COMM_WORLD, STAT_CALL)


                    call MPI_Send (CurrentModel%FatherLink%Window%ILB, 1, MPI_INTEGER,   &
                                   CurrentModel%FatherModel%MPI_ID, tag, MPI_COMM_WORLD, STAT_CALL)
                    call MPI_Send (CurrentModel%FatherLink%Window%IUB, 1, MPI_INTEGER,   &
                                   CurrentModel%FatherModel%MPI_ID, tag, MPI_COMM_WORLD, STAT_CALL)
                    call MPI_Send (CurrentModel%FatherLink%Window%JLB, 1, MPI_INTEGER,   &
                                   CurrentModel%FatherModel%MPI_ID, tag, MPI_COMM_WORLD, STAT_CALL)
                    call MPI_Send (CurrentModel%FatherLink%Window%JUB, 1, MPI_INTEGER,   &
                                   CurrentModel%FatherModel%MPI_ID, tag, MPI_COMM_WORLD, STAT_CALL)


                endif

            endif

            CurrentModel => CurrentModel%Next

        enddo  

        !Waits for all processes
        call MPI_Barrier  (MPI_COMM_WORLD, STAT_CALL)


        !Sends Initial Hydro Information.
        CurrentModel => FirstModel
        do while (associated(CurrentModel))

            !Send the information to the submodels
            if (CurrentModel%MPI_ID == myMPI_ID) then

                do iSub = 1, CurrentModel%nSubModels
                    
                    if (CurrentModel%SubmodelLink(iSub)%Hydro) then
                        call SendHydrodynamicMPI (CurrentModel%HydrodynamicID,           &
                                                  CurrentModel%SubMPIID(iSub),           &
                                                  CurrentModel%SubmodelLink(iSub)%Window,&
                                                  InitialField = .true.,                 &
                                                  STAT = STAT_CALL)
                    end if

                enddo

                if (associated(CurrentModel%FatherModel)) then
                    if (CurrentModel%FatherLink%Hydro) then
                        call RecvHydrodynamicMPI (CurrentModel%HydrodynamicID,              &
                                                  CurrentModel%FatherModel%MPI_ID,          &
                                                  CurrentModel%FatherLink%Window,           &
                                                  InitialField = .true.,                    &
                                                  FatherGridID = CurrentModel%FatherGridID, &
                                                  STAT = STAT_CALL)                                                  
                    endif
                endif

            endif            

            CurrentModel => CurrentModel%Next

        enddo

        !Waits for all processes
        call MPI_Barrier  (MPI_COMM_WORLD, STAT_CALL)

        !Sends Initial Water Information.
        CurrentModel => FirstModel
        do while (associated(CurrentModel))

            !Send the information to the submodels
            if (CurrentModel%MPI_ID == myMPI_ID) then

                do iSub = 1, CurrentModel%nSubModels

                    if (CurrentModel%SubmodelLink(iSub)%Water) then

                        do iProp = 1, CurrentModel%SubmodelLink(iSub)%nProp
                            
                            call SendWaterPropertiesMPI (CurrentModel%WaterPropertiesID,                                    &
                                             CurrentModel%SubMPIID(iSub),                                       &
                                             CurrentModel%SubmodelLink(iSub)%Window,                            &
                                             InitialField = .true.,                                             &
                                             PropIDNumber = CurrentModel%SubmodelLink(iSub)%PropertyIDNumbers(iProp),   &
                                             STAT = STAT_CALL)

                        enddo

                    endif
                enddo

                if (associated(CurrentModel%FatherModel)) then

                    if (CurrentModel%FatherLink%Water) then
                        
                        do iProp = 1, CurrentModel%FatherLink%nProp

                            call RecvWaterPropertiesMPI (CurrentModel%WaterPropertiesID,           &
                                                         CurrentModel%FatherModel%MPI_ID,          &
                                                         CurrentModel%FatherLink%Window,           &
                                                         InitialField = .true.,                    &
                                                         FatherGridID = CurrentModel%FatherGridID, &
                                                         PropIDNumber = CurrentModel%FatherLink%PropertyIDNumbers(iProp), &
                                                         STAT = STAT_CALL)

                        end do

                    end if

                endif


            endif            

            CurrentModel => CurrentModel%Next

        enddo

        !Waits for all processes
        call MPI_Barrier  (MPI_COMM_WORLD, STAT_CALL)



        !Gets System Time
        call GetSystemTime (WorkCycleInitial)
        call cpu_time      (CPUTimeConstructor)

#endif

    end subroutine ConstructMohidWaterMPI

    !--------------------------------------------------------------------------

    subroutine ConstructModelList
        
        !Arguments-------------------------------------------------------------

        !Local-----------------------------------------------------------------
        logical                                     :: TreeExists
        integer                                     :: iTree, STAT_CALL
        integer                                     :: MPI_ID
        type (T_MohidWater), pointer                :: CurrentModel, NextModel
        character(StringLength)                     :: Coment1, Coment2
        character(PathLength)                       :: AuxChar


        !Nullifies First Pointer
        nullify(FirstModel)

        !Verifies if Tree file exists and allocates the list of models
        inquire(file='tree.dat', EXIST = TreeExists)

        if (TreeExists) then

            call UnitsManager(iTree, OPEN_FILE, STAT = STAT_CALL)
            if (STAT_CALL /= SUCCESS_) stop 'ConstructModelList - MohidWater - ERR01'

            open(UNIT = iTree, FILE = 'tree.dat', status = 'OLD')

            read(unit=iTree, fmt=*) Coment1
            read(unit=iTree, fmt=*) Coment2

            MPI_ID  = 0
            Do 
                read(unit=iTree, fmt='(a256)', END=100) AuxChar
                AuxChar = trim(adjustl(AuxChar))
                if (AuxChar(1:1) == '+') then
                    if (RunInParallel) then
                        call AddNewModel(trim(adjustl(AuxChar)), MPI_ID)
                        MPI_ID = MPI_ID + 1
                    else
                        call AddNewModel(trim(adjustl(AuxChar)))
                    endif
                else
                    exit
                endif
            enddo 

100         call UnitsManager(iTree, CLOSE_FILE, STAT = STAT_CALL)
            if (STAT_CALL /= SUCCESS_) stop 'ConstructModelList - MohidWater - ERR02'

        else

            call AddNewModel("*")

        endif

        
        !Determines which models have submodels
        CurrentModel => FirstModel
        do while (associated(CurrentModel))

            NextModel => CurrentModel%Next
doNext:     do while (associated(NextModel))
                
                if (NextModel%ModelLevel  <= CurrentModel%ModelLevel) exit doNext
                
                if (NextModel%ModelLevel  == CurrentModel%ModelLevel+1) then
                    CurrentModel%SubOn     = .true.
                    CurrentModel%nSubModels= CurrentModel%nSubModels + 1
                    NextModel%FatherModel  => CurrentModel
                    if (RunInParallel) then
                        CurrentModel%SubMPIID(CurrentModel%nSubModels) = NextModel%MPI_ID
                    endif
                endif

                NextModel => NextModel%Next
            enddo doNext

            MPI_ID       =  MPI_ID + 1
            CurrentModel => CurrentModel%Next

        enddo
                
    end subroutine ConstructModelList

    !--------------------------------------------------------------------------

    subroutine AddNewModel(AuxString, MPI_ID)

        !Arguments-------------------------------------------------------------
        character(len=*)                            :: AuxString
        integer, optional                           :: MPI_ID

        !Local-----------------------------------------------------------------
        type (T_MohidWater), pointer                :: NewModel
        type (T_MohidWater), pointer                :: PreviousModel
        type (T_MohidWater), pointer                :: CurrentModel

        !Allocates new model
        allocate (NewModel)
        nullify  (NewModel%FatherModel       )
        nullify  (NewModel%Next              )
        nullify  (NewModel%FatherLink%PropertyIDNumbers)

        !Sets data
        NewModel%ModelID      = 0
        if (present(MPI_ID)) then
            NewModel%MPI_ID       = MPI_ID
        else
            NewModel%MPI_ID       = null_int
        endif
!        NewModel%FatherMPI_ID = null_int
        NewModel%ModelLevel   = ModelLevel(AuxString)
        NewModel%ModelName    = ModelName (AuxString, NewModel%ModelLevel)
        NewModel%SubOn        = .false.
        NewModel%nSubModels   = 0
        
        if(RunInParallel) then
            allocate (NewModel%SubMPIID    (nMPI_Processes))
            allocate (NewModel%SubmodelLink(nMPI_Processes))
        else
            nullify  (NewModel%SubMPIID    )
            nullify  (NewModel%SubmodelLink)
        endif

        !Insert into model list
        if (.not. associated(FirstModel)) then
            FirstModel    => NewModel
        else
            PreviousModel => FirstModel
            CurrentModel  => FirstModel%Next
            do while (associated(CurrentModel))
                PreviousModel  => CurrentModel
                CurrentModel   => CurrentModel%Next
            enddo
            CurrentModel       => NewModel
            PreviousModel%Next => NewModel
        endif

    end subroutine AddNewModel
    
    !--------------------------------------------------------------------------

    subroutine ModifyMohidWater
        
        !Arguments-------------------------------------------------------------

        !Local-----------------------------------------------------------------
        logical                                     :: Running
        integer                                     :: STAT_CALL
        type (T_MohidWater), pointer                :: CurrentModel
        logical                                     :: DoNextStep
        real                                        :: DTmin, DTmax


        write(*, *)"-------------------------- MOHID -------------------------"
        write(*, *)
        write(*, *)"Running MOHID, please wait..."
        write(*, *)                    

        Running            = .true.
        GlobalCurrentTime  = GlobalBeginTime


        !Search for initial Min and Max Time Step
        DTmin   = - FillValueReal
        DTmax   =   FillValueReal
        call SearchMinMaxTimeStep (DTmin, DTmax)

        do while (Running)
            
            GlobalCurrentTime = GlobalCurrentTime + DTmin

            if (RunInParallel) then

                CurrentModel => FirstModel
                do while (associated(CurrentModel))

                    if (CurrentModel%MPI_ID == myMPI_ID) then

                        call UpdateTimeAndMapping    (CurrentModel%ModelID, GlobalCurrentTime, DoNextStep, STAT = STAT_CALL)
                        if (STAT_CALL /= SUCCESS_) stop 'ModifyMohidWater - MohidWater - ERR02'

                        if (DoNextStep) then

                            !Waits for information from father
                            if (associated(CurrentModel%FatherModel)) then

                                !Post next recieve...
                                if (CurrentModel%CurrentTime == CurrentModel%InfoTime) then

                                    call ReceiveInformationMPI (CurrentModel)

                                else if (CurrentModel%CurrentTime < CurrentModel%InfoTime) then 

                                    call UpdateSubModelValues (CurrentModel)

                                else if (CurrentModel%CurrentTime > CurrentModel%InfoTime) then

                                    stop 'ModifyMohidWater - MohidWater - ERR02a'

                                endif

                            endif

                            call RunModel(CurrentModel%ModelID, STAT = STAT_CALL)
                            if (STAT_CALL /= SUCCESS_) stop 'ModifyMohidWater - MohidWater - ERR03'

                            call SendInformationMPI (CurrentModel)

                        endif

                    endif

                    CurrentModel => CurrentModel%Next
                enddo

            else

                CurrentModel => FirstModel
                do while (associated(CurrentModel))

                    call UpdateTimeAndMapping (CurrentModel%ModelID, GlobalCurrentTime,  &
                                               DoNextStep, STAT = STAT_CALL)
                    if (STAT_CALL /= SUCCESS_) stop 'ModifyMohidWater - MohidWater - ERR02'

                    if (DoNextStep) then    
                        call SubModelComunication (CurrentModel)
                        call RunModel             (CurrentModel%ModelID, STAT = STAT_CALL)
                        if (STAT_CALL /= SUCCESS_) stop 'ModifyMohidWater - MohidWater - ERR03'
                    endif

                    CurrentModel => CurrentModel%Next
                enddo
            endif
            

            !Search again MinMax, so the test DTmin / 10.0 can be safely done
            !
            DTmin   = - FillValueReal
            DTmax   =   FillValueReal
            call SearchMinMaxTimeStep (DTmin, DTmax)

            if (abs(GlobalCurrentTime - GlobalEndTime) > DTmin / 10.0) then
                Running = .true.
            else
                Running = .false.
            endif

        enddo
    
    end subroutine ModifyMohidWater
    
    !--------------------------------------------------------------------------

    subroutine KillMohidWater

        !Arguments-------------------------------------------------------------

        !Local-----------------------------------------------------------------
        integer                                     :: STAT_CALL
        type (T_MohidWater), pointer                :: CurrentModel

        !Gets System Time
        call GetSystemTime (WorkCycleFinal )
        call cpu_time      (CPUTimeModifier)

        write(*, *)"-------------------------- MOHID -------------------------"
        write(*, *)
        write(*, *)"Shuting down MOHID, please wait..."
        write(*, *)                    

        CurrentModel => FirstModel
        do while (associated(CurrentModel))

            call KillModel(CurrentModel%ModelID, STAT = STAT_CALL)
            if (STAT_CALL /= SUCCESS_) stop 'KillMohidWater - MohidWater - ERR01'

            CurrentModel => CurrentModel%Next
        enddo

        if (MonitorPerformance) then
            call KillWatchGroup (STAT_CALL)
            if (STAT_CALL /= SUCCESS_) stop 'KillMohidWater - MohidWater - ERR02'
        endif

        if (MonitorDT) call UnitsManager (UnitDT, CLOSE_FILE)

        !Total Time
        call GetSystemTime (FinalSystemTime)
        call cpu_time      (TotalCPUTime   )
        ElapsedSeconds = FinalSystemTime - InitialSystemTime

        !WorkCycle Time
        WorkCycleCPUTime = CPUTimeModifier - CPUTimeConstructor
        WorkCycleElapsed = WorkCycleFinal  - WorkCycleInitial

        call ShutdownMohid ("Mohid Water", ElapsedSeconds, TotalCPUTime,                 &
                            WorkCycleElapsed, WorkCycleCPUTime)

    end subroutine KillMohidWater
    
    !--------------------------------------------------------------------------

    subroutine KillMohidWaterMPI

        !Arguments-------------------------------------------------------------
#ifdef _USE_MPI

        !Local-----------------------------------------------------------------
        integer                                     :: STAT_CALL
        type (T_MohidWater), pointer                :: CurrentModel

        !Gets System Time
        call GetSystemTime (WorkCycleFinal)
        call cpu_time      (CPUTimeModifier)


        write(*, *)"-------------------------- MOHID -------------------------"
        write(*, *)
        write(*, *)"Shuting down MOHID, please wait..."
        write(*, *)                    


        CurrentModel => FirstModel
        do while (associated(CurrentModel))
            !The next if statement is important due to the MPI
            if (CurrentModel%MPI_ID == myMPI_ID) then
                call KillModel(CurrentModel%ModelID, STAT = STAT_CALL)
                if (STAT_CALL /= SUCCESS_) stop 'KillMohidWaterMPI - MohidWater - ERR01'
            endif

            !Wait for all processes
            call MPI_Barrier   (MPI_COMM_WORLD, STAT_CALL)

            CurrentModel => CurrentModel%Next
        enddo

        if (MonitorPerformance) then
            call KillWatchGroup (STAT_CALL)
            if (STAT_CALL /= SUCCESS_) stop 'KillMohidWaterMPI - MohidWater - ERR02'
        endif

        if (MonitorDT) call UnitsManager (UnitDT, CLOSE_FILE)

        call MPI_Barrier  (MPI_COMM_WORLD, STAT_CALL)
        if (STAT_CALL /= SUCCESS_) stop 'KillMohidWaterMPI - MohidWater - ERR03'

        call MPI_Finalize (STAT_CALL)
        if (STAT_CALL /= SUCCESS_) stop 'KillMohidWaterMPI - MohidWater - ERR04'

        !Total Time
        call GetSystemTime (FinalSystemTime)
        call cpu_time      (TotalCPUTime   )
        ElapsedSeconds = FinalSystemTime - InitialSystemTime

        !WorkCycle Time
        WorkCycleCPUTime = CPUTimeModifier - CPUTimeConstructor
        WorkCycleElapsed = WorkCycleFinal  - WorkCycleInitial

        call ShutdownMohid ("Mohid Water", ElapsedSeconds, TotalCPUTime,                 &
                            WorkCycleElapsed, WorkCycleCPUTime)

#endif

    end subroutine KillMohidWaterMPI
    
    !--------------------------------------------------------------------------

    subroutine GetSystemTime (Time)

        !Arguments-------------------------------------------------------------
        type (T_Time)                               :: Time

        !Local-----------------------------------------------------------------
        integer, dimension(8)                       :: F95Time

        call date_and_time(Values = F95Time)
        call SetDate      (Time, float(F95Time(1)), float(F95Time(2)),      &
                                 float(F95Time(3)), float(F95Time(5)),      &
                                 float(F95Time(6)), float(F95Time(7))+      &
                                 F95Time(8)/1000.)

    end subroutine GetSystemTime

    !--------------------------------------------------------------------------

    integer function ModelLevel (String)

        !Arguments-------------------------------------------------------------
        Character(len=*), intent(in)                :: String

        !Local-----------------------------------------------------------------
        integer                                     :: Level, i

        if(String(1:1)/='+') then
            ModelLevel=0
        else
            Level=1
do1:        do i=2,StringLength
                if (String(i:i)/='+') exit
                Level=Level+1
            enddo do1
            ModelLevel = Level
        endif

    end function ModelLevel

    !--------------------------------------------------------------------------

    character(len=StringLength) function ModelName (String, Level)

        !Arguments-------------------------------------------------------------
        character(len=*), intent(in)                :: String
        integer,          intent(in)                :: Level

        !Local-----------------------------------------------------------------

        ModelName = ''
        ModelName = String(Level+1:)

    end function ModelName

    !--------------------------------------------------------------------------

    subroutine SetFilesName (Folder)

    !Arguments------------------------------------
    character(LEN=*) :: Folder

    !Begin------------------------------------

    if (trim(Folder) /= '*') FilesName = trim(Folder)//'/nomfich.dat'

    end subroutine SetFilesName

    !--------------------------------------------------------------------------

#ifdef _USE_MPI
    subroutine ConvertIntToStr (FileNameInt, FileNameStr, Length)

        !Arguments-------------------------------------------------------------
        integer                                 :: Length
        integer, dimension(Length)              :: FileNameInt
        character(len = Length)                 :: FileNameStr

        !Local-----------------------------------------------------------------
        integer                                 :: i

        do i = 1, Length
            FileNameStr(i:i) = char(FileNameInt(i))
        enddo

    end subroutine ConvertIntToStr 

    !--------------------------------------------------------------------------

    subroutine ConvertStrToInt (FileNameStr, FileNameInt, Length)

        !Arguments-------------------------------------------------------------
        integer                                 :: Length
        character(len = Length)                 :: FileNameStr
        integer, dimension(Length)              :: FileNameInt

        !Local-----------------------------------------------------------------
        integer                                 :: i
        do i = 1, Length
             FileNameInt(i) = ichar(FileNameStr(i:i))
        enddo

    end subroutine ConvertStrToInt 
#endif
    !--------------------------------------------------------------------------

    subroutine SearchMinMaxTimeStep (DTmin, DTmax)

        !Arguments-------------------------------------------------------------
        real, intent(INOUT)                         :: DTmin, DTmax
        
        !Local-----------------------------------------------------------------
        real                                        :: DT
        integer                                     :: STAT_CALL
        type (T_MohidWater), pointer                :: CurrentModel
#ifdef _USE_MPI
        real, dimension(:), allocatable             :: DTs
        integer                                     :: status(MPI_STATUS_SIZE)
#endif

        !Begin-----------------------------------------------------------------

#ifdef _USE_MPI
        allocate(DTs(nMPI_Processes))


        !Get the DT of the current model
        CurrentModel => FirstModel
        do while (associated(CurrentModel))
            if (CurrentModel%MPI_ID == myMPI_ID) then
                call GetModelTimeStep (CurrentModel%ModelID, DT, STAT = STAT_CALL)
                if (STAT_CALL /= SUCCESS_) stop 'SearchMinMaxTimeStep - MohidWater - ERR01'
            endif
            CurrentModel => CurrentModel%Next
        enddo


        !Sends the information to all the others 
        call MPI_Allgather(DT, 1, Precision, DTs, 1, Precision, MPI_COMM_WORLD, status)

        !Determines the minimum time step
        DTmin = minval(DTs)
        DTmax = maxval(DTs)
        
        deallocate(DTs)
#else
        
        CurrentModel => FirstModel
        do while (associated(CurrentModel))
        
            call GetModelTimeStep (CurrentModel%ModelID, DT, STAT = STAT_CALL)
            if (STAT_CALL /= SUCCESS_) stop 'SearchMinMaxTimeStep - MohidWater - ERR01'
        
            DTmin = min(DT, DTmin)
            DTmax = max(DT, DTmax)

            CurrentModel => CurrentModel%Next
        enddo

#endif

    end subroutine SearchMinMaxTimeStep

    !--------------------------------------------------------------------------

    subroutine SubModelComunication (CurrentModel)

        !Arguments-------------------------------------------------------------
        type (T_MohidWater), pointer                :: CurrentModel

        !Local-----------------------------------------------------------------
        integer                                     :: STAT_CALL, i 

        !----------------------------------------------------------------------

        if (CurrentModel%FatherLink%Hydro) then

             call SetHydroFather (CurrentModel%HydrodynamicID,                           &
                                  CurrentModel%FatherModel%HydrodynamicID,               &
                                  InitialField = .false., STAT = STAT_CALL)
             if (STAT_CALL /= SUCCESS_) stop 'SubModelComunication - MohidWater - ERR01'

        endif

        if (CurrentModel%FatherLink%Water) then

            do i = 1, CurrentModel%FatherLink%nProp

                call SetWaterPropFather (CurrentModel%WaterPropertiesID,                 &
                                         CurrentModel%FatherModel%WaterPropertiesID,     &
                                         CurrentModel%FatherLink%PropertyIDNumbers(i),   &
                                         InitialField= .false., STAT = STAT_CALL)
                if (STAT_CALL /= SUCCESS_) stop 'SubModelComunication - MohidWater - ERR02'

            enddo

        endif

    end subroutine SubModelComunication

    !--------------------------------------------------------------------------

    subroutine ReceiveInformationMPI (CurrentModel)

        !Arguments-------------------------------------------------------------
        type (T_MohidWater), pointer                :: CurrentModel

#ifdef _USE_MPI
        !Local-----------------------------------------------------------------
        integer                                     :: STAT_CALL, tag, iProp
        integer                                     :: status(MPI_STATUS_SIZE)
        real, dimension(6)                          :: AuxTime
        
        !Begin-----------------------------------------------------------------

        call MPI_Recv (AuxTime, 6, Precision, CurrentModel%FatherModel%MPI_ID, tag, MPI_COMM_WORLD, status,  &
                       STAT_CALL)
        if (STAT_CALL /= SUCCESS_) stop 'ReceiveInformationMPI - MohidWater - ERR01'

        call SetDate     (CurrentModel%InfoTime, AuxTime(1), AuxTime(2), AuxTime(3),     &
                          AuxTime(4), AuxTime(5), AuxTime(6))

        if (CurrentModel%FatherLink%Hydro) then
            call RecvHydrodynamicMPI (CurrentModel%HydrodynamicID,             &
                                      CurrentModel%FatherModel%MPI_ID,         &
                                      CurrentModel%FatherLink%Window,          &
                                      InitialField = .false.,                  &
                                      FatherGridID = CurrentModel%FatherGridID,&
                                      STAT = STAT_CALL)
        endif

        if (CurrentModel%FatherLink%Water) then
            
            do iProp = 1, CurrentModel%FatherLink%nProp
                
                call RecvWaterPropertiesMPI (CurrentModel%WaterPropertiesID,           &
                                             CurrentModel%FatherModel%MPI_ID,          &
                                             CurrentModel%FatherLink%Window,           &
                                             InitialField = .false.,                   &
                                             FatherGridID = CurrentModel%FatherGridID, &
                                             PropIDNumber = CurrentModel%FatherLink%PropertyIDNumbers(iProp), &
                                             STAT = STAT_CALL)
            end do

        end if

#else

    !Disable unused variable warnings
    CurrentModel = CurrentModel

#endif

    end subroutine ReceiveInformationMPI

    !--------------------------------------------------------------------------

    subroutine SendInformationMPI (CurrentModel)

        !Arguments-------------------------------------------------------------
        type (T_MohidWater), pointer                :: CurrentModel

#ifdef _USE_MPI
        !Local-----------------------------------------------------------------
        integer                                     :: STAT_CALL, tag, iSub, iProp
        real, dimension(6)                          :: AuxTime

        !Gets the Current Time
        call GetModelCurrentTime (CurrentModel%ModelID, CurrentModel%CurrentTime,        &
                                  STAT = STAT_CALL)
        if (STAT_CALL /= SUCCESS_) stop 'SendInformationMPI - MohidWater - ERR01'

        call ExtractDate (CurrentModel%CurrentTime, AuxTime(1), AuxTime(2), AuxTime(3),  &
                          AuxTime(4), AuxTime(5), AuxTime(6))

        do iSub = 1, CurrentModel%nSubModels

            call MPI_Send (AuxTime, 6, Precision, CurrentModel%SubMPIID(iSub), tag,       &
                           MPI_COMM_WORLD, STAT_CALL)
            if (STAT_CALL /= SUCCESS_) stop 'SendInformationMPI - MohidWater - ERR02'

            if (CurrentModel%SubmodelLink(iSub)%Hydro) then
                call SendHydrodynamicMPI (CurrentModel%HydrodynamicID,                   &
                                          CurrentModel%SubMPIID(iSub),                   &
                                          CurrentModel%SubmodelLink(iSub)%Window,        &
                                          InitialField = .false., STAT = STAT_CALL)
            endif

            if(CurrentModel%SubmodelLink(iSub)%Water)then

                do iProp = 1, CurrentModel%SubmodelLink(iSub)%nProp

                    call SendWaterPropertiesMPI (CurrentModel%WaterPropertiesID,                            &
                                         CurrentModel%SubMPIID(iSub),                                       &
                                         CurrentModel%SubmodelLink(iSub)%Window,                            &
                                         InitialField = .false.,                                            &
                                         PropIDNumber = CurrentModel%SubmodelLink(iSub)%PropertyIDNumbers(iProp),   &
                                         STAT         = STAT_CALL)

                enddo

            end if
            
        enddo

#else

    !Disable unused variable warnings
    CurrentModel = CurrentModel

#endif
    end subroutine SendInformationMPI 

    !--------------------------------------------------------------------------

    subroutine UpdateSubModelValues (CurrentModel)

        !Arguments-------------------------------------------------------------
        type (T_MohidWater), pointer                :: CurrentModel

#ifdef _USE_MPI
        !Local-----------------------------------------------------------------
        integer                                     :: STAT_CALL, iProp

        if (CurrentModel%FatherLink%Hydro) then
            call UpdateHydroMPI (CurrentModel%HydrodynamicID,             &
                                 InitialField = .false.,                  &
                                 STAT = STAT_CALL)
        endif

        if (CurrentModel%FatherLink%Water) then
            
            do iProp = 1, CurrentModel%FatherLink%nProp

                call UpdateWaterMPI (CurrentModel%WaterPropertiesID,           &
                                     InitialField = .false.,                   &
                                     PropIDNumber = CurrentModel%FatherLink%PropertyIDNumbers(iProp), &
                                     STAT = STAT_CALL)

            end do

        end if
#else

    !Disable unused variable warnings
    CurrentModel = CurrentModel

#endif

    end subroutine UpdateSubModelValues


end program MohidWater
