subroutine Drawworks_Solver
    
    Use CUnityInputs
    use UnitySignalVariables
    use UnitySignalsModule
    use SimulationVariables !@
    use OperationScenariosModule
    use OperationScenariosModule !!CElevator...
    use UnitySignalsModule
    ! Use CTdsElevatorModesEnumVariables
    use OperationScenariosModule
    
	IMPLICIT NONE
    
    
    Integer :: j
    Integer :: CrownCollision_Status , FloorCollision_Status , CrownWarning_Status , FloorWarning_Status
    
    
    
    
    
!>>>>>>>>>>>>>>>>>>>> Speed <<<<<<<<<<<<<<<<<<<<<<<<

    data%State%Drawworks%N_Throtle      = data%State%Drawworks%Throttle                                 ![rpm]
    !data%State%Drawworks%N_Accelarator = (data%State%Drawworks%Acceleretor/100.d0)*965.d0              ![rpm]
    
    !IF (data%State%Drawworks%N_Throtle>data%State%Drawworks%N_Accelarator) THEN
        data%State%Drawworks%N_new = data%State%Drawworks%N_Throtle
    !ELSE
    !    data%State%Drawworks%N_new = data%State%Drawworks%N_Accelarator
    !END IF
    
    !========================== Drawworks Rate limit ==========================
    if (((data%State%Drawworks%N_new-data%State%Drawworks%N_old)/data%State%Drawworks%time_step)>data%State%Drawworks%RateChange) then
        data%State%Drawworks%Speed =(data%State%Drawworks%RateChange*data%State%Drawworks%time_step)+data%State%Drawworks%N_old              ![rpm]
    else if (((data%State%Drawworks%N_old-data%State%Drawworks%N_new)/data%State%Drawworks%time_step)>data%State%Drawworks%RateChange) then
        data%State%Drawworks%Speed = (-data%State%Drawworks%RateChange*data%State%Drawworks%time_step)+data%State%Drawworks%N_old
    else
        data%State%Drawworks%Speed = data%State%Drawworks%N_new
    end if
    !=======================================================================
    
    !========================== Speed Correction ==========================
    !===> SLIPS SET , No Motion
    if ( data%State%Drawworks%DriveType==1 .and. Get_Slips() == SLIPS_SET_END .and. Get_KellyConnection() == KELLY_CONNECTION_STRING ) then
        data%State%Drawworks%Speed       = 0.d0
    end if
    if ( data%State%Drawworks%DriveType==0 .and. Get_Slips() == SLIPS_SET_END .and. (Get_TdsConnectionModes()==TDS_CONNECTION_SPINE .or. Get_TdsConnectionModes()==TDS_CONNECTION_STRING) ) then
        data%State%Drawworks%Speed       = 0.d0
    end if
    
    
    !===> Closed BOP Rams , No Motion
    if ( data%State%Drawworks%ShearBopSituation==1 .and. (any(data%State%Drawworks%DrillModeCond==(/3,10,19,20,24/))) ) then
        data%State%Drawworks%Speed       = 0.d0
    end if
    !=======================================================================
    
    
    Call Drawworks_Direction
    
    
    
!====================================================
!               Collision & Warning
!====================================================
    if ( data%State%Drawworks%CrownCollision == .false. ) then
        CrownCollision_Status = 0
    end if
    if ( data%State%Drawworks%FloorCollision == .false. ) then
        FloorCollision_Status = 0
    end if
     
     
     
     
     
     
!====================================================
!        Crown Collision (Max_Hook_Height)
!====================================================
    if ( ((3.280839895d0*data%State%Drawworks%Hook_Height)>=data%State%Drawworks%max_Hook_Height) .and. (any(data%State%Drawworks%DrillModeCond==(/3,4,7,10,11,12,14/))) ) then
        if ( CrownCollision_Status==0 .and. data%State%Drawworks%motion==1 ) then
            CrownCollision_Status         = 1
            data%State%Drawworks%CrownCollision      = .true.
            data%State%Drawworks%SoundCrownCollision = .true.
        else
            data%State%Drawworks%SoundCrownCollision = .false.
        end if
        if ( data%State%Drawworks%motion==-1 .and. data%State%Drawworks%CrownCollision==.false. ) then
            data%State%Drawworks%Hook_Height_final = 3.280839895d0*data%State%Drawworks%Hook_Height    ![ft]
        else
            Call DWFixModeMotion
        end if
        return
    end if
     
     
     
     
     
     
     
!====================================================
!        Floor Collision (Min_Hook_Height)
!====================================================
    if ( ((3.280839895*data%State%Drawworks%Hook_Height)<=data%State%Drawworks%min_Hook_Height) .and. (any(data%State%Drawworks%DrillModeCond==(/3,4,7,10,11,12,14/)))  ) then
        if ( FloorCollision_Status==0 .and. data%State%Drawworks%motion==-1 ) then
            FloorCollision_Status         = 1
            data%State%Drawworks%FloorCollision      = .true.
            data%State%Drawworks%SoundFloorCollision = .true.
        else
            data%State%Drawworks%SoundFloorCollision = .false.
        end if
        if ( data%State%Drawworks%motion==1 .and. data%State%Drawworks%FloorCollision==.false. ) then
            data%State%Drawworks%Hook_Height_final = 3.280839895d0*data%State%Drawworks%Hook_Height    ![ft]
        else
            Call DWFixModeMotion
        end if
        return
    end if
     
     
     
     
     
     
     
     
!====================================================
!                   Crown Warning
!====================================================
    if ( ((3.280839895*data%State%Drawworks%Hook_Height)>=data%State%Drawworks%max_Hook_Height) .and. (any(data%State%Drawworks%DrillModeCond==(/1,2,5,6,8,9,13/))) ) then
        if ( data%State%Drawworks%motion==-1 ) then
            data%State%Drawworks%Hook_Height_final = 3.280839895d0*data%State%Drawworks%Hook_Height    ![ft]
        else
            Call DWFixModeMotion
        end if
        return
    end if
     
     
     
     
     
     
     
!====================================================
!                  Floor Warning
!====================================================
    if ( ((3.280839895*data%State%Drawworks%Hook_Height)<=data%State%Drawworks%min_Hook_Height) .and. (any(data%State%Drawworks%DrillModeCond==(/1,2,5,6,8,9,13/)))  ) then
        if ( data%State%Drawworks%motion==1 ) then
            data%State%Drawworks%Hook_Height_final = 3.280839895d0*data%State%Drawworks%Hook_Height    ![ft]
        else
            Call DWFixModeMotion
        end if
        return
    end if
     
     
     
     
     
     
     
     
     
     
!====================================================
! ELEVATOR CONNECTION STRING (SLIPS SET , No Motion)
!====================================================
    if ( data%State%Drawworks%DriveType==1 .and. Get_Slips() == SLIPS_SET_END .and. Get_ElevatorConnection() == ELEVATOR_CONNECTION_STRING .and. data%State%Drawworks%motion/=-1 ) then
        Call DWFixModeMotion
        return
    end if
     
    if ( data%State%Drawworks%DriveType==0 .and. Get_Slips() == SLIPS_SET_END .and. (Get_TdsConnectionModes()==TDS_CONNECTION_NOTHING .and. Get_TdsElevatorModes()==TDS_ELEVATOR_CONNECTION_STRING) .and. data%State%Drawworks%motion/=-1 ) then
        Call DWFixModeMotion
        return
    end if
     
     
     
     
     
     
     
     
     
     
     
!====================================================
!       RAM & ToolJoint Collision (Top of RAM)
!====================================================
    Do j = 2,4  !startup problem ???????
        if ( data%State%Drawworks%TDBOPElementNo(j)/=0 ) then
            if ( ((data%State%Drawworks%TDBOPHeight(j)-data%State%Drawworks%TDBOPThickness)<=(data%State%Drawworks%TDDrillStemsTopDepth(data%State%Drawworks%TDBOPElementNo(j))+data%State%Drawworks%TDDrillStemsToolJointRange(data%State%Drawworks%TDBOPElementNo(j)))) .and. ((data%State%Drawworks%TDBOPHeight(j)-data%State%Drawworks%TDBOPThickness)>data%State%Drawworks%TDDrillStemsTopDepth(data%State%Drawworks%TDBOPElementNo(j))) .and. (data%State%Drawworks%TDBOPRamDiam(j)<(2.d0*12.d0*data%State%Drawworks%TDDrillStemsRtoolJoint(data%State%Drawworks%TDBOPElementNo(j)))) ) then
                if ( data%State%Drawworks%motion==1 ) then
                    data%State%Drawworks%Hook_Height_final = 3.280839895d0*data%State%Drawworks%Hook_Height    ![ft]
                else
                    Call DWFixModeMotion
                end if
                return
            end if
        end if
    End Do
     
     
     
     
     
     
      
     
     
!====================================================
!      RAM & ToolJoint Collision (Bottom of RAM)
!====================================================
    Do j = 2,4
        if ( data%State%Drawworks%TDBOPElementNo(j)/=0 ) then
            if ( ((data%State%Drawworks%TDBOPHeight(j)+data%State%Drawworks%TDBOPThickness)>=(data%State%Drawworks%TDDrillStemsDownDepth(data%State%Drawworks%TDBOPElementNo(j))-data%State%Drawworks%TDDrillStemsToolJointRange(data%State%Drawworks%TDBOPElementNo(j)))) .and. ((data%State%Drawworks%TDBOPHeight(j)+data%State%Drawworks%TDBOPThickness)<data%State%Drawworks%TDDrillStemsDownDepth(data%State%Drawworks%TDBOPElementNo(j))) .and. (data%State%Drawworks%TDBOPRamDiam(j)<(2.d0*12.d0*data%State%Drawworks%TDDrillStemsRtoolJoint(data%State%Drawworks%TDBOPElementNo(j)))) ) then
                if ( data%State%Drawworks%motion==-1 ) then
                    data%State%Drawworks%Hook_Height_final = 3.280839895d0*data%State%Drawworks%Hook_Height    ![ft]
                else
                    Call DWFixModeMotion
                end if
                return
            end if
        end if
    End Do
     
     
      
      
      
      
      
!====================================================
!               TopDrive (TdsStemIn)
!====================================================
    if ( (data%State%Drawworks%DriveType==0) .and. (Get_TdsStemIn()) .and. Get_Slips() == SLIPS_SET_END ) then
        if ( data%State%Drawworks%motion==1 ) then
            data%State%Drawworks%Hook_Height_final = 3.280839895d0*data%State%Drawworks%Hook_Height    ![ft]
        else
            Call DWFixModeMotion
        end if
        return
    end if
      
      
      
     
     
     
     
     
     
!=====> BottomHole ROP Condition
    if ( (int(data%State%Drawworks%TDDrillStemBottom*10000.d0)>=(int((data%State%Drawworks%TDWellTotalLength+data%State%Drawworks%TDDlMax)*10000.d0))) .and. (data%State%Drawworks%motion==-1 .or. data%State%Drawworks%motion==0) ) then
        if ( data%State%Drawworks%StringIsBottomOfWell==0 ) then
            data%State%Drawworks%Hook_Height_final = data%State%Drawworks%Hook_Height_final+(data%State%Drawworks%TDDrillStemBottom-(data%State%Drawworks%TDWellTotalLength+data%State%Drawworks%TDDlMax))
            data%State%Drawworks%StringIsBottomOfWell = 1
        end if
        Call DWFixModeMotion
        return
    else
        data%State%Drawworks%StringIsBottomOfWell = 0
    end if
     
     
     
      
     
     
     
     
     data%State%Drawworks%Hook_Height_final = 3.280839895d0*data%State%Drawworks%Hook_Height                                  ![ft]
     data%State%Drawworks%HookHeight_graph_output = 0.1189d0*((3.280839895d0*data%State%Drawworks%Hook_Height)-28.d0)-2.6d0   ![ft]
     
    
     
     
end subroutine Drawworks_Solver