#include "cfx5ext.h"
dllexport(tstepcontrol)
C================================================================
      SUBROUTINE tstepcontrol(CZ,DZ,IZ,LZ,RZ)
CC
CD Recalculates timestep size to fit into a maximum and minimum
CD coefficient loops.
CC
CC --------------------
CC        Modified
CC --------------------
CC
CV Stacks
CC
CC --------------------
CC      Modified
CC --------------------
CC
CC --------------------
CC        Output
CC --------------------
CC
CC --------------------
CC Modification History
CC --------------------
CC
CC
CC --------------------
CC Variable dictionary
CC --------------------
CC
CC --------------------
CC Local variables & parameters
CC --------------------
CC
CC   CCLOOP,LCLOOP,NCLOOP    : Coefficient loop name,length, and number
CC   CSTEP,LTSTEP,NTSTEP     : Coefficient step name,length, and number
CC   DT                      : Timestep size
CC   MAXDT,MINDT             : Maximum and minimum timestep size
CC   FACINC,FACDEC           : Increment and decrement factors
CC
CC======================================================================
C
C ------------------------------
C     Preprocessor includes
C ------------------------------
C
#include "MMS.h"
#include "stack_point.h"
#include "cfd_constants.h"
C
C ------------------------------
C        Argument List
C ------------------------------
C
      CHARACTER CZ(*)*(1)
C
      DOUBLE PRECISION DZ(*)
C
      INTEGER IZ(*)
C
      LOGICAL LZ(*)
C
      REAL RZ(*)
C
C ------------------------------
C        External routines
C ------------------------------
C     
      LOGICAL LFIL      
      EXTERNAL CFROMR,CFROMI,LFIL
C
C ------------------------------
C        Local Variables
C ------------------------------
C
      CHARACTER*4 CRESLT
      CHARACTER*(10) CFROMI
      CHARACTER*(20) CCLOOP,CTSTEP,CFROMR,FNAME
C
      INTEGER LCLOOP,NCLOOP,LTSTEP,NTSTEP,MINLOOPS,MAXLOOPS,IUNIT,ICALL
C      
      REAL DT,MAXDT,MINDT,TIME,FACINC,FACDEC
C
C ------------------------------
C        Local Parameters
C ------------------------------
C
      PARAMETER(IUNIT=91,FNAME='dt_ncloop.dat')
C
C--Saved data.
C      
      SAVE ICALL,FACINC,FACDEC,MINDT,MAXDT,MINLOOPS,MAXLOOPS
C
C ------------------------------
C        Stack pointers
C ------------------------------
C
      __stack_point__ pOINT
C
C ---------------------------
C    Executable Statements
C ---------------------------
C
      IF (ICALL.EQ.0) THEN
        ICALL=1
C
C---- Set defaults:
C     MINDT is used to enforce a positive timestep size
C
        MINDT = 0.
        MAXDT = 1.E10
        MINLOOPS=3
        MAXLOOPS=8
C
C---- Negative means: increase by 10/decrease by 0.1 each given 
C     iteration number, positive means: factor itself
C
        FACINC=-40.
        FACDEC=-10.
C
C---- Get from USER area if there:
C
        CALL USER_PEEKR('MINDT',1,MINDT,'SKIP',CRESLT,CZ)
        CALL USER_PEEKR('MAXDT',1,MAXDT,'SKIP',CRESLT,CZ)
        CALL USER_PEEKI('MINLOOPS',1,MINLOOPS,'SKIP',CRESLT,CZ)
        CALL USER_PEEKI('MAXLOOPS',1,MAXLOOPS,'SKIP',CRESLT,CZ)
        CALL USER_PEEKR('FACINC',1,FACINC,'SKIP',CRESLT,CZ)
        CALL USER_PEEKR('FACDEC',1,FACDEC,'SKIP',CRESLT,CZ)
C
C---- Increment by factor 10 each ## time steps
C
        IF (FACINC.LE.0) FACINC=10.**(1./ABS(FACINC))
C
C---- Decrement by factor 0.1 each ## time steps
C
        IF (FACDEC.LE.0) FACDEC=0.1**(1./ABS(FACDEC))
C
C---- Output parameters
C
        CALL MESAGE('WRITE','MINDT is '//CFROMR(MINDT))
        CALL MESAGE('WRITE','MAXDT is '//CFROMR(MAXDT))
        CALL MESAGE('WRITE','MINLOOPS is '//CFROMI(MINLOOPS))
        CALL MESAGE('WRITE','MAXLOOPS is '//CFROMI(MAXLOOPS))
        CALL MESAGE('WRITE','FACINC is '//CFROMR(FACINC)//
     &              ' ('//CFROMI(INT( 1./LOG10(FACINC)+0.5))//')')
        CALL MESAGE('WRITE','FACDEC is '//CFROMR(FACDEC)//
     &              ' ('//CFROMI(INT(-1./LOG10(FACDEC)+0.5))//')')
        IF (IUNIT>0) OPEN(UNIT=IUNIT,FILE=FNAME)
      END IF
C
C---- Get transient info
C
      CALL USER_GET_TRANS_INFO('TSTEPCONTROL','GET',' ',
     &                         CZ,DZ,IZ,LZ,RZ)
C
C---- Get time step
C
      CALL PEEKR('/USER/TRANS_INFO/DT',1,DT,'STOP',CRESLT,RZ)
C
C---- Write into file
C
      IF (IUNIT>0) THEN
C
C---- Get time and current coefficient loop
C
        CALL PEEKR('/USER/TRANS_INFO/ATIME',1,TIME,'STOP',CRESLT,RZ)      
        CALL PEEKI('/USER/TRANS_INFO/NCLOOP',1,NCLOOP,'STOP',CRESLT,IZ)
        WRITE(IUNIT,*) DT,NCLOOP,TIME
C
      END IF
C
C---- Control structure
C
      CALL MESAGE('WRITE','Number of coeff loops was: '//CFROMI(NCLOOP))
C
      IF (NCLOOP.LT.MINLOOPS) THEN
        DT=MIN(FACINC*DT,MAXDT)
        CALL MESAGE('WRITE','Time step increased to: '//CFROMR(DT))
      ELSE IF (NCLOOP.GT.MAXLOOPS) THEN
        DT=FACDEC*DT
        IF (MINDT.LE.0.AND.DT.LE.-MINDT) THEN
          IF (IUNIT.GT.0) CLOSE(IUNIT)
          CALL MESAGE('WRITE','Stop program due to bad convergence.')
          OPEN(UNIT=91,FILE='stp')
          WRITE(91,*) ' '
          CLOSE(91)
        END IF
          DT=MAX(DT,MINDT)
          CALL MESAGE('WRITE','Time step decreased to: '//CFROMR(DT))
      ELSE
        CALL MESAGE('WRITE','Time step stayed at: '//CFROMR(DT))
      END IF
C
C---- Set new time step
C
      IF (.NOT.LFIL('/USER/NEWDT')) THEN
        CALL PSHDIR ('/USER','STOP',CRESLT)
          CALL MAKDAT('NEWDT','REAL','STOP',1,pOINT,CRESLT)
        CALL POPDIR ('STOP',CRESLT)          
      ENDIF
      CALL POKER('/USER/NEWDT',1,DT,'STOP',CRESLT,RZ)
C
C---- Release transient data
C
      CALL USER_GET_TRANS_INFO('TSTEPCONTROL','RELEASE',' ',
     &                         CZ,DZ,IZ,LZ,RZ)
C     
      END
