!------------------------------------------------------------------------------
!        IST/MARETEC, Water Modelling Group, Mohid modelling system
!------------------------------------------------------------------------------
!
! TITLE         : Mohid Model
! PROJECT       : Mohid Water
! MODULE        : Model
! URL           : http://www.mohid.com
! AFFILIATION   : IST/MARETEC, Marine Modelling Group
! DATE          : June 2003
! REVISION      : Frank Braunschweig - v4.0
! DESCRIPTION   : Module which coordinates the evolution of one Model (Main or SubModel)
!------------------------------------------------------------------------------

Module ModuleModel

    use ModuleGlobalData
    use ModuleFunctions,                only : ReadTimeKeywords
    use ModuleEnterData           
    use ModuleTime
    use ModuleHorizontalGrid,           only : ConstructHorizontalGrid, KillHorizontalGrid                                       
    use ModuleGridData,                 only : ConstructGridData, KillGridData
    use ModuleHorizontalMap,            only : ConstructHorizontalMap,  KillHorizontalMap,  &
                                               GetWaterPoints2D, UnGetHorizontalMap
    use ModuleGeometry,                 only : ConstructGeometry,       KillGeometry
    use ModuleMap,                      only : ConstructMap,            KillMap,         &
                                               UpdateComputeFaces3D
    use ModuleTurbulence,               only : ConstructTurbulence, Turbulence,          &
                                               KillTurbulence, GetTurbulenceOptions
    use ModuleHydrodynamic,             only : StartHydrodynamic, GetWaterLevel,         &
                                               GetHorizontalVelocity, GetChezy,          &
                                               GetVerticalVelocity,                      &
                                               Modify_Hydrodynamic, UnGetHydrodynamic,   &
                                               KillHydrodynamic          
    use ModuleWaterProperties,          only : Construct_WaterProperties,                &
                                               GetDensity, GetConcentration, GetSigma,   &
                                               UnGetWaterProperties,                     &
                                               WaterProperties_Evolution,                &
                                               KillWaterProperties
#ifndef _LAGRANGIAN_
    use ModuleLagrangian,               only : ConstructLagrangian, ModifyLagrangian,    &
                                               KillLagrangian
#endif

#ifndef _SEDIMENT_
    use ModuleConsolidation,            only : ConstructConsolidation, KillConsolidation,&
                                               ModifyConsolidation

    use ModuleSedimentProperties,       only : Construct_SedimentProperties,             &
                                               SedimentProperties_Evolution,             &
                                               KillSedimentProperties
#endif

    use ModuleInterfaceSedimentWater,   only : StartInterfaceSedimentWater,              &
                                               ModifyInterfaceSedimentWater,             &
                                               KillInterfaceSedimentWater
#ifndef _AIR_
    use ModuleInterfaceWaterAir,        only : StartInterfaceWaterAir,                   &
                                               ModifyInterfaceWaterAir,                  &
                                               KillInterfaceWaterAir

    use ModuleAtmosphere,               only : StartAtmosphere,                          &
                                               ModifyAtmosphere,                         &
                                               KillAtmosphere
#endif

#ifndef _WAVES_
    use ModuleWaves,                    only : StartWaves, ModifyWaves, KillWaves,       &
                                               ComputeWaveParameters, GetWavesOptions
#endif


    implicit none

    private

    !Subroutines--------------------------------------------

    !Constructor
    public  :: ConstructModel

    !Modifier
    public  :: UpdateTimeAndMapping
    public  :: RunModel

    !Destructor
    public  :: KillModel

    !Selector
    public  :: GetModelTimeLimits 
    public  :: GetModelTimeStep
    public  :: GetModelCurrentTime
    public  :: GetModelInstanceIDs
    

    !Management
    private :: AllocateInstance
    private :: DeallocateInstance
    private :: Read_Lock
    private :: Read_Unlock
    private :: Ready


    !Type----------------------------------------------------------------------
    type T_ExternalVar
        real, dimension(:,:,:), pointer :: Density, SigmaDens   => null()
        real, dimension(:,:,:), pointer :: Salinity             => null()
        real, dimension(:,:,:), pointer :: Temperature          => null()
        real, dimension(:,:,:), pointer :: VelocityX            => null()
        real, dimension(:,:,:), pointer :: VelocityY            => null()
        real, dimension(:,:,:), pointer :: VelocityZ            => null()
        real, dimension(:,:  ), pointer :: Chezy, WaterLevel    => null()
        logical                         :: NeedsTempSalinity
    end type T_ExternalVar

    !Groups modules of the WaterColumn
    type T_Column
        integer                         :: ObjBathymetry    = 0
        integer                         :: ObjHorizontalMap = 0
        integer                         :: ObjGeometry      = 0
        integer                         :: ObjMap           = 0
    end type T_Column


    !public :: T_Model
    type T_Model 

        integer                         :: InstanceID
        character(StringLength)         :: ModelName
            
        type (T_ExternalVar)            :: ExternalVar   

        type (T_Time)                   :: CurrentTime
        type (T_Time)                   :: BeginTime
        type (T_Time)                   :: EndTime
        real                            :: DT, MaxDT
        logical                         :: VariableDT
        real                            :: InitialDT
        real                            :: GmtReference

        logical                         :: RunSediments
        logical                         :: RunLagrangian
        logical                         :: RunWaves
        logical                         :: NoIsolatedCells

        !Instance of other Modules
        integer                         :: ObjTime                  = 0
        integer                         :: ObjHorizontalGrid        = 0
        type (T_Column)                 :: Water
        type (T_Column)                 :: Sediment
        integer                         :: ObjAssimilation          = 0
        integer                         :: ObjDischarges            = 0
        integer                         :: ObjTurbGOTM              = 0
        integer                         :: ObjTurbulence            = 0
        integer                         :: ObjHydrodynamic          = 0
        integer                         :: ObjWaterProperties       = 0
        integer                         :: ObjLagrangian            = 0
        integer                         :: ObjAtmosphere            = 0
        integer                         :: ObjWaves                 = 0
        integer                         :: ObjInterfaceWaterAir     = 0
        integer                         :: ObjInterfaceSedimentWater= 0
!        integer                         :: ObjInterfaceSedAir      = 0
        integer                         :: ObjSedimentProperties    = 0
        integer                         :: ObjConsolidation         = 0

        !Linked list of Instances
        type(T_Model), pointer          :: Next

    End Type T_Model 


    !Global Module Variables
    type (T_Model), pointer             :: FirstModel
    type (T_Model), pointer             :: Me

    Contains

    !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

    !CONSTRUCTOR CONSTRUCTOR CONSTRUCTOR CONSTRUCTOR CONSTRUCTOR CONSTRUCTOR CO

    !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    
    !In this subroutine is read the model structure (number of parallel models and their sub-models) 
    ! and the necessary memory is allocate and store in a structure of pointer lists
    
    subroutine ConstructModel (ModelID, ModelName, STAT)

        !Arguments-------------------------------------------------------------
        integer                                     :: ModelID 
        character(len=*)                            :: ModelName   
        integer, intent(OUT), optional              :: STAT

        !Local----------------------------------------------------------------- 
        integer                                     :: STAT_ 
        integer                                     :: STAT_CALL, ready_
        integer                                     :: FromFile, flag
        character(PathLength)                       :: BathymetryFile, DataFile
#ifndef _SEDIMENT_
        character(PathLength)                       :: SedimentFile, SedGeometryFile
#endif
        integer                                     :: ObjEnterData = 0
#ifndef _AIR_
        integer, dimension(:, :), pointer           :: WaterPoints2D
#endif
#ifndef _WAVES_
        logical                                     :: WaveParametersON
#endif
        !----------------------------------------------------------------------

        STAT_ = UNKNOWN_

        !Assures nullification of the global variable
        if (.not. ModuleIsRegistered(mModel_)) then
            nullify (FirstModel)
            call RegisterModule (mModel_) 
        endif

        call Ready(ModelID, ready_)    

if0 :   if (ready_ .EQ. OFF_ERR_) then

            call AllocateInstance 

            !Stores name
            Me%ModelName = ModelName

            write(*, *)"-------------------------- MODEL -------------------------"
            write(*, *)
            write(*, *)"Constructing      : ", trim(Me%ModelName)
            write(*, *)"ID                : ", Me%InstanceID


            !Gets the name of the data file
            call ReadFileName('IN_MODEL', DataFile, "Compute Time Data File", STAT = STAT_CALL)
            if (STAT_CALL /= SUCCESS_) stop 'ConstructModel - ModuleModel - ERR01'

            !Constructs EnterData
            call ConstructEnterData (ObjEnterData, DataFile, STAT = STAT_CALL)
            if (STAT_CALL /= SUCCESS_) stop 'ConstructModel - ModuleModel - ERR12'

            !Read the Time related keywords
            call GetExtractType  (FromFile = FromFile)
            call ReadTimeKeyWords(ObjEnterData, FromFile, Me%BeginTime, Me%EndTime,      &
                                  Me%DT, Me%VariableDT, "Model", Me%MaxDT, Me%GmtReference)
            Me%InitialDT = Me%DT

            !Use Sediment columns
            call GetData         (Me%RunSediments, ObjEnterData, flag,                   &
                                  SearchType    =  FromFile,                             &
                                  keyword       = 'SEDIMENT_COLUMN',                     &
                                  default       = .false.,                               &
                                  ClientModule  = 'ModuleModel',                         &
                                  STAT          = STAT_CALL)
            if (STAT_CALL /= SUCCESS_) stop 'ConstructModel - ModuleModel - ERR20'


            !Use Lagrangian
            call GetData         (Me%RunLagrangian, ObjEnterData, flag,                  &
                                  SearchType    =  FromFile,                             &
                                  keyword       = 'LAGRANGIAN',                          &
                                  default       = .false.,                               &
                                  ClientModule  = 'ModuleModel',                         &
                                  STAT          = STAT_CALL)
            if (STAT_CALL /= SUCCESS_) stop 'ConstructModel - ModuleModel - ERR30'

            !Use Waves
            call GetData         (Me%RunWaves, ObjEnterData, flag,                       &
                                  SearchType    =  FromFile,                             &
                                  keyword       = 'WAVES',                               &
                                  default       = .false.,                               &
                                  ClientModule  = 'ModuleModel',                         &
                                  STAT          = STAT_CALL)
            if (STAT_CALL /= SUCCESS_) stop 'ConstructModel - ModuleModel - ERR40'

            call GetData         (Me%NoIsolatedCells, ObjEnterData, flag,                &
                                  SearchType    =  FromFile,                             &
                                  keyword       = 'NO_ISOLATED_CELLS',                      &
                                  default       = .true.,                                &
                                  ClientModule  = 'ModuleModel',                         &
                                  STAT          = STAT_CALL)
            if (STAT_CALL /= SUCCESS_) stop 'ConstructModel - ModuleModel - ERR45'

            call KillEnterData    (ObjEnterData, STAT = STAT_CALL)
            if (STAT_CALL /= SUCCESS_) stop 'ConstructModel - ModuleModel - ERR50'



            !Start Module Time
            Me%CurrentTime = Me%BeginTime
            call StartComputeTime(Me%ObjTime, Me%BeginTime, Me%EndTime, Me%DT,     &
                                  Me%VariableDT, Me%MaxDT, Me%GmtReference, STAT = STAT_CALL)   
            if (STAT_CALL /= SUCCESS_) stop 'ConstructModel - ModuleModel - ERR60'

            !Gets the file name of the Bathymetry
            call ReadFileName('IN_BATIM', BathymetryFile, "Bathymetry File", STAT = STAT_CALL)
            if (STAT_CALL /= SUCCESS_) stop 'ConstructModel - ModuleModel - ERR70'

            !Horizontal Grid
            call ConstructHorizontalGrid(HorizontalGridID = Me%ObjHorizontalGrid,        &
                                         DataFile         = BathymetryFile,              &
                                         STAT             = STAT_CALL)
            if (STAT_CALL /= SUCCESS_) stop 'ConstructModel - ModuleModel - ERR90'

            !Horizontal Grid Data - Water Column (Bathymetry)
            call ConstructGridData      (GridDataID       = Me%Water%ObjBathymetry,      &
                                         HorizontalGridID = Me%ObjHorizontalGrid,        &
                                         TimeID           = Me%ObjTime,                  &
                                         FileName         = BathymetryFile,              &
                                         STAT             = STAT_CALL)
            if (STAT_CALL /= SUCCESS_) stop 'ConstructModel - ModuleModel - ERR100'

            !Horizontal Map
            call ConstructHorizontalMap (HorizontalMapID  = Me%Water%ObjHorizontalMap,   &
                                         GridDataID       = Me%Water%ObjBathymetry,      &
                                         HorizontalGridID = Me%ObjHorizontalGrid,        &
                                         ActualTime       = Me%CurrentTime,              &
                                         STAT             = STAT_CALL)  
            if (STAT_CALL /= SUCCESS_) stop 'ConstructModel - ModuleModel - ERR110'

            !Geometry - Water Column
            call ConstructGeometry      (GeometryID       = Me%Water%ObjGeometry,        &
                                         GridDataID       = Me%Water%ObjBathymetry,      &
                                         HorizontalGridID = Me%ObjHorizontalGrid,        &
                                         HorizontalMapID  = Me%Water%ObjHorizontalMap,   &
                                         ActualTime       = Me%CurrentTime,              &
                                         STAT             = STAT_CALL)  
            if (STAT_CALL /= SUCCESS_) stop 'ConstructModel - ModuleModel - ERR120'

            !Map - Water Column            
            if (Me%NoIsolatedCells) then
                call ConstructMap           (Map_ID           = Me%Water%ObjMap,          &
                                             GeometryID       = Me%Water%ObjGeometry,     &
                                             HorizontalMapID  = Me%Water%ObjHorizontalMap,&
                                             TimeID           = Me%ObjTime,               &
                                             GridDataID       = Me%Water%ObjBathymetry,   &
                                             HorizontalGridID = Me%ObjHorizontalGrid,     &
                                             STAT             = STAT_CALL)  
                if (STAT_CALL /= SUCCESS_) stop 'ConstructModel - ModuleModel - ERR130'
            else

                call ConstructMap           (Map_ID           = Me%Water%ObjMap,          &
                                             GeometryID       = Me%Water%ObjGeometry,     &
                                             HorizontalMapID  = Me%Water%ObjHorizontalMap,&
                                             TimeID           = Me%ObjTime,               &
                                             HorizontalGridID = Me%ObjHorizontalGrid,     &
                                             STAT             = STAT_CALL)  
                if (STAT_CALL /= SUCCESS_) stop 'ConstructModel - ModuleModel - ERR135'

            endif

#ifndef _WAVES_
            if(Me%RunWaves)then

                call StartWaves(WavesID             = Me%ObjWaves,                          &
                                TimeID              = Me%ObjTime,                           &
                                HorizontalMapID     = Me%Water%ObjHorizontalMap,            &
                                HorizontalGridID    = Me%ObjHorizontalGrid,                 &
                                GridDataID          = Me%Water%ObjBathymetry,               &
                                GeometryID          = Me%Water%ObjGeometry,                 &
                                STAT                = STAT_CALL)
                if (STAT_CALL /= SUCCESS_) stop "Sub. ConstructModel - ModuleModel - ERR140"

            end if
#else
            write(*,*)
            write(*,*)"<Compilation Options Warning>"
            write(*,*)"This executable was not compiled with the Waves module."
            if (Me%RunWaves) then
                stop 'ConstructModel - ModuleModel - ERR141'
            endif
            write(*,*)"<Compilation Options Warning>"
            write(*,*)

#endif

            !Turbulence
            call ConstructTurbulence    (TurbulenceID     = Me%ObjTurbulence,            &
                                         TurbGOTMID       = Me%ObjTurbGOTM,              &
                                         HorizontalGridID = Me%ObjHorizontalGrid,        &
                                         GeometryID       = Me%Water%ObjGeometry,        &
                                         MapID            = Me%Water%ObjMap,             &
                                         GridDataID       = Me%Water%ObjBathymetry,      &
                                         HorizontalMapID  = Me%Water%ObjHorizontalMap,   &
                                         TimeID           = Me%ObjTime,                  &
                                         STAT             = STAT_CALL)
            if (STAT_CALL /= SUCCESS_) stop 'ConstructModel - ModuleModel - ERR150'

            call GetTurbulenceOptions   (TurbulenceID     = Me%ObjTurbulence,            &
                                         NeedsTempSalinity= Me%ExternalVar%NeedsTempSalinity, &
                                         STAT             = STAT_CALL)
            if (STAT_CALL /= SUCCESS_) stop 'ConstructModel - ModuleModel - ERR151'

            !Constructs hydrodynamic
            call StartHydrodynamic      (HydrodynamicID   = Me%ObjHydrodynamic,          &
                                         GridDataID       = Me%Water%ObjBathymetry,      &
                                         HorizontalGridID = Me%ObjHorizontalGrid,        &
                                         GeometryID       = Me%Water%ObjGeometry,        &
                                         HorizontalMapID  = Me%Water%ObjHorizontalMap,   &
                                         MapID            = Me%Water%ObjMap,             &
                                         AssimilationID   = Me%ObjAssimilation,          &
                                         TimeID           = Me%ObjTime,                  &
                                         TurbulenceID     = Me%ObjTurbulence,            &
                                         DischargesID     = Me%ObjDischarges,            &
                                         WavesID          = Me%ObjWaves,                 &
                                         STAT             = STAT_CALL)
            if (STAT_CALL /= SUCCESS_) stop 'ConstructModel - ModuleModel - ERR160'


#ifndef _WAVES_
            !Need the watercolumn thickness that is compute the first time in the StartHydrodynamic
            if(Me%RunWaves)then
                call GetWavesOptions(Me%ObjWaves, WaveParametersON = WaveParametersON, STAT  = STAT_CALL)
                if (STAT_CALL /= SUCCESS_) stop 'ConstructModel - ModuleModel - ERR170'
                
                if (WaveParametersON) then
                    call ComputeWaveParameters(Me%ObjWaves, STAT  = STAT_CALL)
                    if (STAT_CALL /= SUCCESS_) stop 'ConstructModel - ModuleModel - ERR180'
                endif
            endif
#endif

            !Constructs waterProperties
            call Construct_WaterProperties(WaterPropertiesID= Me%ObjWaterProperties,     &
                                           GridDataID       = Me%Water%ObjBathymetry,    &
                                           HorizontalGridID = Me%ObjHorizontalGrid,      &
                                           GeometryID       = Me%Water%ObjGeometry,      &
                                           HorizontalMapID  = Me%Water%ObjHorizontalMap, &
                                           MapID            = Me%Water%ObjMap,           &
                                           HydrodynamicID   = Me%ObjHydrodynamic,        &
                                           TimeID           = Me%ObjTime,                &     
                                           TurbulenceID     = Me%ObjTurbulence,          &
                                           AssimilationID   = Me%ObjAssimilation,        &
                                           DischargesID     = Me%ObjDischarges,          &
                                           STAT             = STAT_CALL)
            if (STAT_CALL /= SUCCESS_) stop "Sub. ConstructModel - ModuleModel - ERR200"

#ifndef _LAGRANGIAN_

            if (Me%RunLagrangian) then

                call ConstructLagrangian(LagrangianID       = Me%ObjLagrangian,             &
                                         TimeID             = Me%ObjTime,                   &
                                         GridDataID         = Me%Water%ObjBathymetry,       &
                                         HorizontalGridID   = Me%ObjHorizontalGrid,         &
                                         HorizontalMapID    = Me%Water%ObjHorizontalMap,    &
                                         GeometryID         = Me%Water%ObjGeometry,         &
                                         MapID              = Me%Water%ObjMap,              &
                                         AssimilationID     = Me%ObjAssimilation,           &
                                         HydrodynamicID     = Me%ObjHydrodynamic,           &
                                         TurbulenceID       = Me%ObjTurbulence,             &
                                         WavesID            = Me%ObjWaves,                  &
                                         WaterPropertiesID  = Me%ObjWaterProperties,        &
                                         STAT               = STAT_CALL)
                if (STAT_CALL /= SUCCESS_) stop "Sub. ConstructModel - ModuleModel - ERR210"
            end if
#else
            write(*,*)
            write(*,*)"<Compilation Options Warning>"
            write(*,*)"This executable was not compiled with the Lagrangian module."
            if (Me%RunLagrangian) then
                stop 'ConstructModel - ModuleModel - ERR211'
            endif
            write(*,*)"<Compilation Options Warning>"
            write(*,*)

#endif

#ifndef _SEDIMENT_

            if (Me%RunSediments) then

                !Gets the file name of the Bathymetry
                call ReadFileName('IN_SEDIMENT', SedimentFile, "Sediment File", STAT = STAT_CALL)
                if (STAT_CALL /= SUCCESS_) stop 'ConstructModel - ModuleModel - ERR215'

                !Gets the file name of the Bathymetry
                call ReadFileName('SED_GEOM', SedGeometryFile, "Sediment Geometry File", STAT = STAT_CALL)
                if (STAT_CALL /= SUCCESS_) stop 'ConstructModel - ModuleModel - ERR216'

                !Horizontal Grid Data - Sediment Column (Bathymetry)
                call ConstructGridData      (GridDataID       = Me%Sediment%ObjBathymetry,   &
                                             HorizontalGridID = Me%ObjHorizontalGrid,        &
                                             FileName         = SedimentFile,                &
                                             STAT             = STAT_CALL)
                if (STAT_CALL /= SUCCESS_) stop 'ConstructModel - ModuleModel - ERR220'

                !Horizontal Map
                call ConstructHorizontalMap (HorizontalMapID  = Me%Sediment%ObjHorizontalMap,&
                                             GridDataID       = Me%Sediment%ObjBathymetry,   &
                                             HorizontalGridID = Me%ObjHorizontalGrid,        &
                                             ActualTime       = Me%CurrentTime,              &
                                             STAT             = STAT_CALL)  
                if (STAT_CALL /= SUCCESS_) stop 'ConstructModel - ModuleModel - ERR230'

                !Geometry - Sediment Column
                call ConstructGeometry      (GeometryID       = Me%Sediment%ObjGeometry,     &
                                             GridDataID       = Me%Sediment%ObjBathymetry,   &
                                             HorizontalGridID = Me%ObjHorizontalGrid,        &
                                             HorizontalMapID  = Me%Sediment%ObjHorizontalMap,&
                                             ActualTime       = Me%CurrentTime,              &
                                             NewDomain        = SedGeometryFile,             &
                                             STAT             = STAT_CALL)  
                if (STAT_CALL /= SUCCESS_) stop 'ConstructModel - ModuleModel - ERR240'

                !Map - Sediment Column            
                call ConstructMap           (Map_ID           = Me%Sediment%ObjMap,          &
                                             GeometryID       = Me%Sediment%ObjGeometry,     &
                                             HorizontalMapID  = Me%Sediment%ObjHorizontalMap,&
                                             TimeID           = Me%ObjTime,                  &
                                             STAT             = STAT_CALL)  
                if (STAT_CALL /= SUCCESS_) stop 'ConstructModel - ModuleModel - ERR250'


                call ConstructConsolidation(ConsolidationID     = Me%ObjConsolidation,          &
                                            TimeID              = Me%ObjTime,                   &
                                            GridDataID          = Me%Sediment%ObjBathymetry,    &
                                            HorizontalMapID     = Me%Sediment%ObjHorizontalMap, &
                                            HorizontalGridID    = Me%ObjHorizontalGrid,         &
                                            GeometryID          = Me%Sediment%ObjGeometry,      &
                                            MapID               = Me%Sediment%ObjMap,           &
                                            STAT                = STAT_CALL)
                if (STAT_CALL /= SUCCESS_) stop 'ConstructModel - ModuleModel - ERR260'


                !Constructs SedimentProperties
                call Construct_SedimentProperties(SedimentPropertiesID  = Me%ObjSedimentProperties,     &
                                                  TimeID                = Me%ObjTime,                   &     
                                                  HorizontalGridID      = Me%ObjHorizontalGrid,         &
                                                  GridDataID            = Me%Sediment%ObjBathymetry,    &
                                                  HorizontalMapID       = Me%Sediment%ObjHorizontalMap, &
                                                  MapID                 = Me%Sediment%ObjMap,           &
                                                  GeometryID            = Me%Sediment%ObjGeometry,      &
                                                  ConsolidationID       = Me%ObjConsolidation,          &
                                                  STAT                  = STAT_CALL)
                if (STAT_CALL /= SUCCESS_) stop 'ConstructModel - ModuleModel - ERR270'

            endif
#else
            write(*,*)
            write(*,*)"<Compilation Options Warning>"
            write(*,*)"This executable was not compiled with the Sediment modules."
            if(Me%RunSediments)then
                stop 'ConstructModel - ModuleModel - ERR271'
            endif
            write(*,*)"<Compilation Options Warning>"
            write(*,*)

#endif

            call StartInterfaceSedimentWater(ObjInterfaceSedimentWaterID = Me%ObjInterfaceSedimentWater, &
                                             TimeID                      = Me%ObjTime,                   &     
                                             HorizontalGridID            = Me%ObjHorizontalGrid,         &
                                             WaterGridDataID             = Me%Water%ObjBathymetry,       &
                                             WaterHorizontalMapID        = Me%ObjHorizontalGrid,         &
                                             WaterMapID                  = Me%Water%ObjMap,              &
                                             WaterGeometryID             = Me%Water%ObjGeometry,         &
                                             SedimentGridDataID          = Me%Sediment%ObjBathymetry,    &
                                             SedimentHorizontalMapID     = Me%Sediment%ObjHorizontalMap, &
                                             SedimentMapID               = Me%Sediment%ObjMap,           &
                                             SedimentGeometryID          = Me%Sediment%ObjGeometry,      &
                                             HydrodynamicID              = Me%ObjHydrodynamic,           &
                                             TurbGOTMID                  = Me%ObjTurbGOTM,               &
                                             TurbulenceID                = Me%ObjTurbulence,             &
                                             WaterPropertiesID           = Me%ObjWaterProperties,        &
                                             WavesID                     = Me%ObjWaves,                  &
                                             LagrangianID                = Me%ObjLagrangian,             &
                                             SedimentPropertiesID        = Me%ObjSedimentProperties,     &
                                             ConsolidationID             = Me%ObjConsolidation,          &
                                             DischargesID                = Me%ObjDischarges,             &
                                             RunsSediments               = Me%RunSediments,              &
                                             STAT                        = STAT_CALL)
            if (STAT_CALL /= SUCCESS_) stop 'ConstructModel - ModuleModel - ERR280'

#ifndef _AIR_

            !Starts Atmosphere
            call GetWaterPoints2D (Me%Water%ObjHorizontalMap, WaterPoints2D, STAT = STAT_CALL)
            if (STAT_CALL /= SUCCESS_) stop 'ConstructModel - ModuleModel - ERR290'

            call StartAtmosphere(AtmosphereID       = Me%ObjAtmosphere,                              &
                                 TimeID             = Me%ObjTime,                                    &
                                 GridDataID         = Me%Water%ObjBathymetry,                        &
                                 HorizontalGridID   = Me%ObjHorizontalGrid,                          &
                                 MappingPoints      = WaterPoints2D,                                 &
                                 STAT = STAT_CALL)
            if (STAT_CALL /= SUCCESS_) stop 'ConstructModel - ModuleModel - ERR300'

            call UnGetHorizontalMap (Me%Water%ObjHorizontalMap, WaterPoints2D, STAT = STAT_CALL)
            if (STAT_CALL /= SUCCESS_) stop 'ConstructModel - ModuleModel - ERR310'

            call StartInterfaceWaterAir(ObjInterfaceWaterAirID      = Me%ObjInterfaceWaterAir,      &
                                        TimeID                      = Me%ObjTime,                   &     
                                        HorizontalGridID            = Me%ObjHorizontalGrid,         &
                                        WaterGridDataID             = Me%Water%ObjBathymetry,       &
                                        WaterHorizontalMapID        = Me%ObjHorizontalGrid,         &
                                        WaterMapID                  = Me%Water%ObjMap,              &
                                        WaterGeometryID             = Me%Water%ObjGeometry,         &
                                        HydrodynamicID              = Me%ObjHydrodynamic,           &
                                        TurbGOTMID                  = Me%ObjTurbGOTM,               &
                                        WavesID                     = Me%ObjWaves,                  &  
                                        WaterPropertiesID           = Me%ObjWaterProperties,        &
                                        AtmosphereID                = Me%ObjAtmosphere,             &
                                        LagrangianID                = Me%ObjLagrangian,             &
                                        STAT                        = STAT_CALL)
            if (STAT_CALL /= SUCCESS_) stop 'ConstructModel - ModuleModel - 320'
#else
            write(*,*)
            write(*,*)"<Compilation Options Warning>"
            write(*,*)"This executable was not compiled with the Interface Water-Air module."
            write(*,*)"<Compilation Options Warning>"
            write(*,*)

#endif

            !Returns ID
            ModelID     = Me%InstanceID
            STAT_       = SUCCESS_

        else 

            stop 'ModuleModel - ConstructModel - ERR99' 

        end if if0


        if (present(STAT)) STAT = STAT_

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

    End Subroutine ConstructModel 

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

    subroutine AllocateInstance 

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

        !Local-----------------------------------------------------------------
        type (T_Model), pointer                     :: NewModel
        type (T_Model), pointer                     :: PreviousModel


        !Allocates new instance
        allocate (NewModel)
        nullify  (NewModel%Next)

        !Insert New Instance into list and makes Current point to it
        if (.not. associated(FirstModel)) then
            FirstModel    => NewModel
            Me            => NewModel
        else
            PreviousModel => FirstModel
            Me            => FirstModel%Next
            do while (associated(Me))
                PreviousModel  => Me
                Me             => Me%Next
            enddo
            Me                 => NewModel
            PreviousModel%Next => NewModel
        endif

        Me%InstanceID = RegisterNewInstance (mMODEL_)

    end subroutine AllocateInstance

    !--------------------------------------------------------------------------
    
    subroutine GetModelTimeLimits (ModelID, BeginTime, EndTime, STAT)

        !Arguments------------------------------------------------------------ 
        integer                                     :: ModelID
        type (T_Time), intent(OUT)                  :: BeginTime, EndTime
        integer,       intent(OUT),   optional      :: STAT

        !Local-----------------------------------------------------------------
        integer                                     :: STAT_, ready_

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

        STAT_ = UNKNOWN_

        call Ready(ModelID, ready_) 
        
if1 :   if ((ready_ .EQ. IDLE_ERR_     ) .OR.                                            &
            (ready_ .EQ. READ_LOCK_ERR_)) then

            BeginTime = Me%BeginTime
            EndTime   = Me%EndTime
                
            STAT_ = SUCCESS_
        else 
            STAT_ = ready_
        end if if1

        if (present(STAT)) STAT = STAT_

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

    end subroutine GetModelTimeLimits

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

    subroutine GetModelTimeStep (ModelID, DT, STAT)

        !Arguments------------------------------------------------------------ 
        integer                                     :: ModelID
        real, intent(OUT)                           :: DT
        integer,       intent(OUT),   optional      :: STAT

        !Local-----------------------------------------------------------------
        integer                                     :: STAT_, ready_
        integer                                     :: STAT_CALL

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

        STAT_ = UNKNOWN_

        call Ready(ModelID, ready_) 
        
if1 :   if ((ready_ .EQ. IDLE_ERR_     ) .OR.                                            &
            (ready_ .EQ. READ_LOCK_ERR_)) then

            call GetComputeTimeStep  (Me%ObjTime, DT, STAT = STAT_CALL)
            if (STAT_CALL /= SUCCESS_) stop 'GetModelTimeStep - ModuleModel - ERR01'
                
            STAT_ = SUCCESS_
        else 
            STAT_ = ready_
        end if if1

        if (present(STAT)) STAT = STAT_

    end subroutine GetModelTimeStep

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

    subroutine GetModelCurrentTime (ModelID, CurrentTime, STAT)

        !Arguments------------------------------------------------------------ 
        integer                                     :: ModelID
        type (T_Time)                               :: CurrentTime
        integer,       intent(OUT),   optional      :: STAT

        !Local-----------------------------------------------------------------
        integer                                     :: STAT_, ready_

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

        STAT_ = UNKNOWN_

        call Ready(ModelID, ready_) 
        
if1 :   if ((ready_ .EQ. IDLE_ERR_     ) .OR.                                            &
            (ready_ .EQ. READ_LOCK_ERR_)) then
    
            CurrentTime = Me%CurrentTime
                           
            STAT_ = SUCCESS_
        else 
            STAT_ = ready_
        end if if1

        if (present(STAT)) STAT = STAT_

    end subroutine GetModelCurrentTime

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

    subroutine GetModelInstanceIDs (ModelID, HorizontalGridID, HydrodynamicID,           &
                                    WaterPropertiesID, STAT)

        !Arguments------------------------------------------------------------ 
        integer                                     :: ModelID
        integer, intent(OUT), optional              :: HorizontalGridID
        integer, intent(OUT), optional              :: HydrodynamicID
        integer, intent(OUT), optional              :: WaterPropertiesID
        integer, intent(OUT), optional              :: STAT

        !Local-----------------------------------------------------------------
        integer                                     :: STAT_, ready_

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

        STAT_ = UNKNOWN_

        call Ready(ModelID, ready_) 
        
if1 :   if ((ready_ .EQ. IDLE_ERR_     ) .OR.                                            &
            (ready_ .EQ. READ_LOCK_ERR_)) then

            if (present(HorizontalGridID )) HorizontalGridID  = Me%ObjHorizontalGrid
            if (present(HydrodynamicID   )) HydrodynamicID    = Me%ObjHydrodynamic
            if (present(WaterPropertiesID)) WaterPropertiesID = Me%ObjWaterProperties
                
            STAT_ = SUCCESS_
        else 
            STAT_ = ready_
        end if if1

        if (present(STAT)) STAT = STAT_

    end subroutine GetModelInstanceIDs

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

    !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

    !MODIFIER MODIFIER MODIFIER MODIFIER MODIFIER MODIFIER MODIFIER MODIFIER MO 

    !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

    subroutine UpdateTimeAndMapping (ModelID, Global_CurrentTime, DoNextStep, STAT)

        !Arguments-------------------------------------------------------------
        integer                                     :: ModelID
        type (T_Time),     intent(IN )              :: Global_CurrentTime
        logical                                     :: DoNextStep
        integer, optional, intent(OUT)              :: STAT

        !Local-----------------------------------------------------------------
        integer                                     :: STAT_, ready_
        integer                                     :: STAT_CALL

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

        STAT_ = UNKNOWN_

        call Ready(ModelID, ready_)

if1 :   if (ready_ .EQ. IDLE_ERR_) then

            !Gives the actualized Current time to the module time
            call GetComputeCurrentTime(Me%ObjTime, Me%CurrentTime, STAT = STAT_CALL)
            if (STAT_CALL /= SUCCESS_) stop 'UpdateTimeAndMapping - ModuleModel - ERR01'

            DoNextStep = .false.

if9:        if (Me%CurrentTime .LT. Me%EndTime) then      

if2:            if (Global_CurrentTime .GE. Me%CurrentTime) then

                    call GetComputeTimeStep (Me%ObjTime, Me%DT, STAT = STAT_CALL)
                    if (STAT_CALL /= SUCCESS_) stop 'UpdateTimeAndMapping - ModuleModel - ERR03'

                    !Actualize the CurrentTime with Model time interval AppTime%DT
                    call ActualizeCurrentTime(Me%ObjTime, Me%DT, STAT = STAT_CALL)
                    if (STAT_CALL /= SUCCESS_) stop 'UpdateTimeAndMapping - ModuleModel - ERR04'
                   
                    !Gives the actualized Current time to the module time
                    call GetComputeCurrentTime(Me%ObjTime, Me%CurrentTime, STAT = STAT_CALL)
                    if (STAT_CALL /= SUCCESS_) stop 'UpdateTimeAndMapping - ModuleModel - ERR05'

                    call GetWaterLevel(Me%ObjHydrodynamic, Me%ExternalVar%WaterLevel,    &
                                       STAT = STAT_CALL)
                    if (STAT_CALL /= SUCCESS_) stop 'UpdateTimeAndMapping - ModuleModel - ERR06'

                    !Update the moving boundary  (boundary of the tidal areas covered)
                    call UpdateComputeFaces3D(Me%Water%ObjMap, Me%ExternalVar%WaterLevel, &
                                              Me%CurrentTime, STAT = STAT_CALL)      
                    if (STAT_CALL /= SUCCESS_) stop 'UpdateTimeAndMapping - ModuleModel - ERR07'

                    call UnGetHydrodynamic(Me%ObjHydrodynamic,                     &
                                           Me%ExternalVar%WaterLevel, STAT = STAT_CALL)
                    if (STAT_CALL /= SUCCESS_) stop 'UpdateTimeAndMapping - ModuleModel - ERR08'

                    if (Me%CurrentTime < Me%EndTime) then
                        DoNextStep = .true.
                    endif

                end if if2

            end if if9

            STAT_ = SUCCESS_

        else               

            STAT_ = ready_

        end if if1

        if (present(STAT)) STAT = STAT_

    end subroutine UpdateTimeAndMapping

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

    subroutine RunModel(ModelID, STAT)

        !Arguments-------------------------------------------------------------
        integer                                     :: ModelID
        integer, optional, intent(OUT)              :: STAT

        !Local-----------------------------------------------------------------
        real                                        :: CPUTime, LastCPUTime = 0.
        real                                        :: NewDT
        real                                        :: PredictedDT
        integer                                     :: STAT_, ready_
        integer                                     :: STAT_CALL
#ifndef _AIR_
        integer, dimension(:, :), pointer           :: WaterPoints2D
#endif
        !----------------------------------------------------------------------

        STAT_ = UNKNOWN_

        call Ready(ModelID, ready_)

if1 :   if (ready_ .EQ. IDLE_ERR_) then

            !Updates the Interface between the sediment and the water column
            call ModifyInterfaceSedimentWater (Me%ObjInterfaceSedimentWater, STAT = STAT_CALL)
            if (STAT_CALL /= SUCCESS_) stop 'RunModel - ModuleModel - ERR00'

#ifndef _AIR_
            
            !Gets Waterpoints
            call GetWaterPoints2D (Me%Water%ObjHorizontalMap, WaterPoints2D, STAT = STAT_CALL)
            if (STAT_CALL /= SUCCESS_) stop 'RunModel - ModuleModel - ERR01'

            !Starts Atmosphere
            call ModifyAtmosphere  (Me%ObjAtmosphere, MappingPoints = WaterPoints2D, STAT = STAT_CALL)
            if (STAT_CALL /= SUCCESS_) stop 'RunModel - ModuleModel - ERR02'

            !Gets Unget Waterpoints
            call UnGetHorizontalMap (Me%Water%ObjHorizontalMap, WaterPoints2D, STAT = STAT_CALL)
            if (STAT_CALL /= SUCCESS_) stop 'RunModel - ModuleModel - ERR03'

            call ModifyInterfaceWaterAir (Me%ObjInterfaceWaterAir, STAT = STAT_CALL)
            if (STAT_CALL /= SUCCESS_) stop 'RunModel - ModuleModel - ERR04'
#endif
#ifndef _WAVES_
            if(Me%RunWaves)then
                                
                call ModifyWaves(Me%ObjWaves, STAT = STAT_CALL)
                if (STAT_CALL /= SUCCESS_) stop 'RunModel - ModuleModel - ERR05'
                
            end if
#endif
            call GetDensity(Me%ObjWaterProperties, Me%ExternalVar%Density,              &
                            Me%CurrentTime,  STAT = STAT_CALL)
            if (STAT_CALL /= SUCCESS_) stop 'RunModel - ModuleModel - ERR06'

            call GetSigma(Me%ObjWaterProperties, Me%ExternalVar%SigmaDens,              &
                            Me%CurrentTime,  STAT = STAT_CALL)
            if (STAT_CALL /= SUCCESS_) stop 'RunModel - ModuleModel - ERR06a'


            if(Me%ExternalVar%NeedsTempSalinity)then

                call GetConcentration(Me%ObjWaterProperties, Me%ExternalVar%Salinity,   &
                                      Salinity_, STAT = STAT_CALL)
                if (STAT_CALL /= SUCCESS_)stop 'RunModel - ModuleModel - ERR07'

                call GetConcentration(Me%ObjWaterProperties, Me%ExternalVar%Temperature,&
                                      Temperature_, STAT = STAT_CALL)
                if (STAT_CALL /= SUCCESS_)stop 'RunModel - ModuleModel - ERR08'

            endif

            call GetHorizontalVelocity(Me%ObjHydrodynamic,                               &
                                       Me%ExternalVar%VelocityX,                         &
                                       Me%ExternalVar%VelocityY,                         &
                                       STAT = STAT_CALL)
            if (STAT_CALL /= SUCCESS_) stop 'RunModel - ModuleModel - ERR10'

            call GetVerticalVelocity(HydrodynamicID = Me%ObjHydrodynamic,                &
                                       Velocity_W = Me%ExternalVar%VelocityZ,            &
                                       STAT = STAT_CALL)
            if (STAT_CALL /= SUCCESS_) stop 'RunModel - ModuleModel - ERR11'
            call GetChezy(Me%ObjHydrodynamic, Me%ExternalVar%Chezy, STAT = STAT_CALL)

            if (STAT_CALL /= SUCCESS_) stop 'RunModel - ModuleModel - ERR12'
                        
            call Turbulence(Me%ObjTurbulence,                          &
                            Me%ExternalVar%VelocityX,                  &
                            Me%ExternalVar%VelocityY,                  &
                            Me%ExternalVar%VelocityZ,                  &
                            Me%ExternalVar%Chezy,                      &
                            Me%ExternalVar%Salinity,                   &
                            Me%ExternalVar%Temperature,                &
                            STAT = STAT_CALL)
            if (STAT_CALL /= SUCCESS_) stop 'RunModel - ModuleModel - ERR13'

            call UnGetHydrodynamic(Me%ObjHydrodynamic,                 &
                                   Me%ExternalVar%VelocityX, STAT = STAT_CALL)
            if (STAT_CALL /= SUCCESS_) stop 'RunModel - ModuleModel - ERR14'


            call UnGetHydrodynamic(Me%ObjHydrodynamic,                 &
                                   Me%ExternalVar%VelocityY, STAT = STAT_CALL)
            if (STAT_CALL /= SUCCESS_) stop 'RunModel - ModuleModel - ERR15'

            
            call UnGetHydrodynamic(Me%ObjHydrodynamic,                 &
                                   Me%ExternalVar%VelocityZ, STAT = STAT_CALL)
            if (STAT_CALL /= SUCCESS_) stop 'RunModel - ModuleModel - ERR16'

            call UnGetHydrodynamic(Me%ObjHydrodynamic,                 &
                                   Me%ExternalVar%Chezy, STAT = STAT_CALL)
            if (STAT_CALL /= SUCCESS_) stop 'RunModel - ModuleModel - ERR17'

            PredictedDT = Me%DT             
            call Modify_Hydrodynamic(Me%ObjHydrodynamic,                   &
                                     Me%ExternalVar%Density,               &
                                     Me%ExternalVar%SigmaDens,             &
                                     PredictedDT,                          &
                                     STAT = STAT_CALL)
            if (STAT_CALL /= SUCCESS_) stop 'RunModel - ModuleModel - ERR18'
                    

            call UnGetWaterProperties(Me%ObjWaterProperties, Me%ExternalVar%Density,     &
                                      STAT = STAT_CALL)
            if (STAT_CALL /= SUCCESS_) stop 'RunModel - ModuleModel - ERR19'

            call UnGetWaterProperties(Me%ObjWaterProperties, Me%ExternalVar%SigmaDens,     &
                                      STAT = STAT_CALL)
            if (STAT_CALL /= SUCCESS_) stop 'RunModel - ModuleModel - ERR19a'


            if(Me%ExternalVar%NeedsTempSalinity)then

                call UnGetWaterProperties(Me%ObjWaterProperties, Me%ExternalVar%Salinity,    &
                                          STAT = STAT_CALL)
                if (STAT_CALL /= SUCCESS_) stop 'RunModel - ModuleModel - ERR20'

                call UnGetWaterProperties(Me%ObjWaterProperties, Me%ExternalVar%Temperature, &
                                          STAT = STAT_CALL)
                if (STAT_CALL /= SUCCESS_) stop 'RunModel - ModuleModel - ERR21'

            end if

            call WaterProperties_Evolution(Me%ObjWaterProperties, STAT = STAT_CALL)
            if (STAT_CALL /= SUCCESS_) stop 'RunModel - ModuleModel - ERR22'


#ifndef _SEDIMENT_
            if(Me%RunSediments)then
                
                call ModifyConsolidation(Me%ObjConsolidation,               STAT = STAT_CALL)
                if (STAT_CALL /= SUCCESS_) stop 'RunModel - ModuleModel - ERR23'


                call SedimentProperties_Evolution(Me%ObjSedimentProperties, STAT = STAT_CALL)
                if (STAT_CALL /= SUCCESS_) stop 'RunModel - ModuleModel - ERR24'

            end if
#endif

 
#ifndef _LAGRANGIAN_
           if (Me%ObjLagrangian /= 0) then
                call ModifyLagrangian   (Me%ObjLagrangian, STAT = STAT_CALL)
                if (STAT_CALL /= SUCCESS_) stop 'RunModel - ModuleModel - ERR25'
            endif
#endif 

           if (Me%VariableDT) then

                NewDT = PredictedDT

                if (NewDT > Me%DT) then
                    !At maximum increase DT by 5%
                    NewDT = min(Me%DT * 1.05, NewDT)
                endif

                !Dont allow DT superior to Maximum DT
                if (NewDT > Me%MaxDT) then
                    NewDT = Me%MaxDT
                endif

                !Dont allow DT below Initial DT
                if (NewDT < Me%InitialDT) then
                    NewDT = Me%InitialDT
                endif


                !Fit DT so model will stop at the right time
                if (Me%CurrentTime + NewDT > Me%EndTime) then
                    NewDT = Me%EndTime - Me%CurrentTime
                endif

                if (MonitorDT) call WriteDTLog ('ModuleModel', -99, NewDT)

                !Actualize the Time Step
                call ActualizeDT(Me%ObjTime, NewDT, STAT = STAT_CALL)     
                if (STAT_CALL /= SUCCESS_) stop 'RunModel - ModuleModel - ERR26'

           endif 


            call CPU_TIME(CPUTime)
            if (CPUTime - LastCPUTime > 60.) then
                LastCPUTime = CPUTime
                call PrintProgress(Me%ObjTime, STAT = STAT_CALL)
                if (STAT_CALL /= SUCCESS_) stop 'RunModel - ModuleModel - ERR27'
            endif
                

            STAT_ = SUCCESS_
        else               

            STAT_ = ready_

        end if if1

        if (present(STAT)) STAT = STAT_

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

    end subroutine RunModel

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

    !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

    !DESTRUCTOR DESTRUCTOR DESTRUCTOR DESTRUCTOR DESTRUCTOR DESTRUCTOR DESTRUCT 

    !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

    subroutine KillModel (ModelID, STAT)

        !Arguments-------------------------------------------------------------
        integer                                     :: ModelID
        integer, optional, intent(OUT)              :: STAT

        !Local-----------------------------------------------------------------
        integer                                     :: STAT_, ready_
        integer                                     :: nUsers
        integer                                     :: STAT_CALL
        real                                        :: DT_Error
               

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

        STAT_ = UNKNOWN_

        call Ready(ModelID, ready_)    

cd1 :   if (ready_ .NE. OFF_ERR_) then

            nUsers = DeassociateInstance(mMODEL_,  Me%InstanceID)

            if (nUsers == 0) then

                call GetComputeCurrentTime(Me%ObjTime, Me%CurrentTime, STAT = STAT_CALL)
                if (STAT_CALL /= SUCCESS_) stop 'KillModel - ModuleModel - ERR01'

                DT_error = Me%EndTime - Me%CurrentTime
if9 :           if (DT_error /= 0.) then
                    write(*,*)  
                    write(*,*) 'Warning: The model = ',Me%ModelName                  
                    write(*,*) 'Didnt finish in the foreseen data'                   

if7 :               if     (DT_error > 0) then
                        write(*,*) 'The model stoped ',DT_error,' seconds before the foreseen data!'                  
                    elseif (DT_error < 0) then if7
                        write(*,*) 'The model stoped ',DT_error,' seconds after the foreseen data!'                             
                    end if if7
                    write(*,*) '                        '
                    write(*,*) 'SUBROUTINE KillModel; ModuleModel. WRN01.'
                    write(*,*)  
                end if if9

                !Last Progress message
                call PrintProgress(Me%ObjTime, STAT = STAT_CALL)
                if (STAT_CALL /= SUCCESS_) stop 'KillModel - ModuleModel - ERR10'

                call KillInterfaceSedimentWater (Me%ObjInterfaceSedimentWater, STAT = STAT_CALL)
                if (STAT_CALL /= SUCCESS_) stop 'KillModel - ModuleModel - ERR20'
#ifndef _AIR_
                call KillInterfaceWaterAir (Me%ObjInterfaceWaterAir, STAT = STAT_CALL)
                if (STAT_CALL /= SUCCESS_) stop 'KillModel - ModuleModel - ERR30'
#endif
#ifndef _LAGRANGIAN_
                if (Me%ObjLagrangian /= 0) then
                    call KillLagrangian (Me%ObjLagrangian, STAT = STAT_CALL)
                    if (STAT_CALL /= SUCCESS_) stop 'KillModel - ModuleModel - ERR40'
                endif
#endif
#ifndef _AIR_
                call KillAtmosphere (Me%ObjAtmosphere, STAT = STAT_CALL)
                if (STAT_CALL /= SUCCESS_) stop 'KillModel - ModuleModel - ERR50'
#endif
#ifndef _SEDIMENT_
                if (Me%RunSediments) then

                    call KillSedimentProperties (Me%ObjSedimentProperties,      STAT = STAT_CALL)
                    if (STAT_CALL /= SUCCESS_) stop 'KillModel - ModuleModel - ERR95'         

                    call KillConsolidation      (Me%ObjConsolidation,  STAT = STAT_CALL)
                    if (STAT_CALL /= SUCCESS_) stop 'KillModel - ModuleModel - ERR95'

                    !Kills Map
                    call KillMap                (Me%Sediment%ObjMap,           STAT = STAT_CALL)
                    if (STAT_CALL /= SUCCESS_) stop 'KillModel - ModuleModel - ERR60'

                    !Kills Geometry
                    call KillGeometry           (Me%Sediment%ObjGeometry,      STAT = STAT_CALL)
                    if (STAT_CALL /= SUCCESS_) stop 'KillModel - ModuleModel - ERR70'

                    !Kills HorizontalMap
                    call KillHorizontalMap      (Me%Sediment%ObjHorizontalMap, STAT = STAT_CALL)
                    if (STAT_CALL /= SUCCESS_) stop 'KillModel - ModuleModel - ERR80'

                    !Kills Bathymetry
                    call KillGridData           (Me%Sediment%ObjBathymetry,    STAT = STAT_CALL)
                    if (STAT_CALL /= SUCCESS_) stop 'KillModel - ModuleModel - ERR90'


                endif
#endif

                !Kills water properties
                call KillWaterProperties(Me%ObjWaterProperties,     STAT = STAT_CALL)
                if (STAT_CALL /= SUCCESS_) stop 'KillModel - ModuleModel - ERR100'

                !Kills hydrodynamic properties
                call KillHydrodynamic(Me%ObjHydrodynamic,           STAT = STAT_CALL)
                if (STAT_CALL /= SUCCESS_) stop 'KillModel - ModuleModel - ERR110'

                !Kill Turbulence
                call KillTurbulence     (Me%ObjTurbulence,          STAT = STAT_CALL)
                if (STAT_CALL /= SUCCESS_) stop 'KillModel - ModuleModel - ERR120'
#ifndef _WAVES_
                if (Me%ObjWaves /= 0) then
                    call KillWaves (Me%ObjWaves, STAT = STAT_CALL)
                    if (STAT_CALL /= SUCCESS_) stop 'KillModel - ModuleModel - ERR130'
                endif
#endif
                !Kills Map
                call KillMap            (Me%Water%ObjMap,           STAT = STAT_CALL)
                if (STAT_CALL /= SUCCESS_) stop 'KillModel - ModuleModel - ERR140'

                !Kills Geometry
                call KillGeometry       (Me%Water%ObjGeometry,      STAT = STAT_CALL)
                if (STAT_CALL /= SUCCESS_) stop 'KillModel - ModuleModel - ERR150'

                !Kills HorizontalMap
                call KillHorizontalMap  (Me%Water%ObjHorizontalMap, STAT = STAT_CALL)
                if (STAT_CALL /= SUCCESS_) stop 'KillModel - ModuleModel - ERR160'

                !Kills Bathymetry
                call KillGridData       (Me%Water%ObjBathymetry,    STAT = STAT_CALL)
                if (STAT_CALL /= SUCCESS_) stop 'KillModel - ModuleModel - ERR170'

                !Kills HorizontalGrid
                call KillHorizontalGrid (Me%ObjHorizontalGrid,      STAT = STAT_CALL)
                if (STAT_CALL /= SUCCESS_) stop 'KillModel - ModuleModel - ERR180'

                !Kills Compute Time
                call KillComputeTime    (Me%ObjTime,                STAT = STAT_CALL)
                if (STAT_CALL /= SUCCESS_) stop 'KillModel - ModuleModel - ERR190'

                !ObjHorizontalGrid
                call DeallocateInstance
                
                ModelID = 0
                STAT_   = SUCCESS_

            end if

        else 

            STAT_ = ready_

        end if cd1


        if (present(STAT)) STAT = STAT_

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

    End Subroutine KillModel
    
    !--------------------------------------------------------------------------

    subroutine DeallocateInstance

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

        !Local-----------------------------------------------------------------
        type (T_Model), pointer          :: AuxObjModel
        type (T_Model), pointer          :: PreviousObjModel

        !Updates pointers
        if (Me%InstanceID == FirstModel%InstanceID) then
            FirstModel => FirstModel%Next
        else
            PreviousObjModel => FirstModel
            AuxObjModel      => FirstModel%Next
            do while (AuxObjModel%InstanceID /= Me%InstanceID)
                PreviousObjModel => AuxObjModel
                AuxObjModel      => AuxObjModel%Next
            enddo

            !Now update linked list
            PreviousObjModel%Next => AuxObjModel%Next

        endif

        !Deallocates instance
        deallocate (Me)
        nullify    (Me) 
            
    end subroutine DeallocateInstance

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

    !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

    !MANAGEMENT MANAGEMENT MANAGEMENT MANAGEMENT MANAGEMENT MANAGEMENT MANAGEME

    !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

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

    subroutine Ready (ModelID, ready_) 

        !Arguments-------------------------------------------------------------
        integer                                     :: ModelID
        integer                                     :: ready_

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

        nullify (Me)

cd1:    if (ModelID > 0) then

            Me => FirstModel
            do while (associated (Me))
                if (Me%InstanceID == ModelID) exit
                Me => Me%Next
            enddo

            if (.not. associated(Me)) stop 'ModuleModel - Ready - ERR01'

            ready_ = VerifyReadLock (mMODEL_, Me%InstanceID)
        else
            ready_ = OFF_ERR_
        end if cd1

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

    end subroutine Ready

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

end module ModuleModel
