This Junction Box subroutine should be called at the end of
each timestep in a transient run. It is designed to dynamically control
the timestep size during the transient run. The algorithm is similar
to one of the adaptive timestepping algorithms available in the solver,
but serves to illustrate how a junction box can be used to control
the timestep size. The algorithm for modifying the timestep is as
follows: if the previous timestep needed more iterations than MAXLOOPS, the next timestep size is decreased by a factor FACDEC. If the previous timestep needed fewer iterations
than MINLOOPS, the next timestep size is increased
by a factor FACINC. The junction box calls USER_GET_TRANS_INFO to retrieve current timestep data
and creates a data area called ‘NEWDT’ to store the next timestep size. The procedure requires a User CEL
function called Retrieve_deltat to use the timestep
calculated by the junction box. Retrieve_deltat requires an additional argument (passed in through the argument
list) called ‘Timesteps’, which
will be the initial timestep size. The routines t_step_control.F and Retrieve_deltat.F are supplied in the
<CFXROOT>/examples/UserFortran/ directory of your CFX installation.
The following is a listing of t_step_control.F:
#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======================================================================
CC ------------------------------
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
ENDThe following is a listing of Retrieve_deltat.F:
#include "cfx5ext.h"
dllexport(get_timestep)
SUBROUTINE get_timestep (
& NLOC,NRET,NARG,RET,ARGS,CRESLT,CZ,DZ,IZ,LZ,RZ)
CC
CD User routine: retrieves delta t stored in /USER directory
CC
CC --------------------
CC Input
CC --------------------
CC
CC NLOC - size of current locale
CC NRET - number of components in result
CC NARG - number of arguments in call
CC ARGS() - (NLOC,NARG) argument values
CC
CC --------------------
CC Modified
CC --------------------
CC
CC Stacks possibly.
CC
CC --------------------
CC Output
CC --------------------
CC
CC RET() - (NLOC,NRET) return values
CC CRESLT - 'GOOD' for success
CC
CC --------------------
CC Details
CC --------------------
CC
CC======================================================================
C
C ------------------------------
C Preprocessor includes
C ------------------------------
C
#include "MMS.h"
#include "cfd_constants.h"
C
C ------------------------------
C Global Parameters
C ------------------------------
C
C
C ------------------------------
C Argument list
C ------------------------------
C
CHARACTER CRESLT*(*)
CHARACTER CZ(*)*(1)
C
DOUBLE PRECISION DZ(*)
C
INTEGER IZ(*)
INTEGER NLOC,NARG,NRET
C
LOGICAL LZ(*)
C
REAL RZ(*)
REAL ARGS(NLOC,NARG), RET(NLOC,NRET)
C
C
C ------------------------------
C External routines
C ------------------------------
C
C
C ------------------------------
C Local Parameters
C ------------------------------
C
C
C ------------------------------
C Local Variables
C ------------------------------
C
CHARACTER*(4) CRES
C
REAL DT
C
C ---------------------------
C Executable Statements
C ---------------------------
C
C
C Set success flag.
C
CRES = 'GOOD'
C
C---- Retrieves DT value. If there is none, it uses default the value
C passed as argument.
C
CALL PEEKR('/USER/NEWDT',IONE,DT,'SKIP',CRES,RZ)
IF (CRES .NE. 'GOOD') DT = ARGS(1,1)
RET(1,1) = DT
C
END