1 MODULE ADJUST_DT 2 3 CONTAINS 4 5 !vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv! 6 ! ! 7 ! Module name: ADJUST_DT(IER, NIT) ! 8 ! Author: M. Syamlal Date: FEB-10-97 ! 9 ! ! 10 ! Purpose: Automatically adjust time step. ! 11 ! ! 12 !^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^! 13 LOGICAL FUNCTION ADJUSTDT (IER, NIT) 14 15 ! Global Variables: 16 !---------------------------------------------------------------------// 17 ! User defined type of run: new or restart 18 use run, only: RUN_TYPE 19 ! User defined aximum number of iterations 20 use leqsol, only: MAX_NIT 21 ! User defined: min, max DT and adjustment factor 22 use run, only: DT_MIN, DT_MAX, DT_FAC 23 ! Flag: Use stored DT value for advancing TIME 24 use run, only: USE_DT_PREV 25 ! Flag: 2nd order time implementation 26 use run, only: CN_ON 27 ! Flag: Continue to run at DT_MIN 28 use run, only: PERSISTENT_MODE 29 ! Flag: Running in interactive mode 30 use run, only: INTERACTIVE_MODE 31 ! Flag: Interupt the code in interactive mode 32 use run, only: INTERUPT 33 ! The current number of time steps (value at restart). 34 use run, only: NSTEP, NSTEPRST 35 ! Current DT (1/DT) and direction of last change (+/-) 36 use run, only: DT, oDT, DT_DIR 37 38 ! Global Parameters: 39 !---------------------------------------------------------------------// 40 use param1, only: ZERO, ONE, UNDEFINED 41 42 43 ! Module proceedures: 44 !---------------------------------------------------------------------// 45 ! Routine to break successive time step reductions. 46 use interactive, only: CHECK_TIMESTEP_FAIL_RATE 47 use error_manager 48 49 IMPLICIT NONE 50 51 ! Dummy Arguments: 52 !---------------------------------------------------------------------// 53 ! Integer flag: 0=Good, 100=initialize, otherwise bad. 54 INTEGER, INTENT(INOUT) :: IER 55 ! Number of iterations for current time step 56 INTEGER, INTENT(IN) :: NIT 57 58 59 ! Local Variables: 60 !---------------------------------------------------------------------// 61 ! Number of steps in between DT adjustments. 62 INTEGER, PARAMETER :: STEPS_MIN = 5 63 ! Number of time steps since last DT adjustment 64 INTEGER, SAVE :: STEPS_TOT=0 65 ! number of iterations since last DT adjustment 66 INTEGER, SAVE :: NIT_TOT=0 67 ! Iterations per second for last dt 68 DOUBLE PRECISION, SAVE :: NIToS=0.0 69 ! Current number of iterations per second 70 DOUBLE PRECISION :: NITOS_NEW 71 ! Flag to half/double the current time step 72 LOGICAL :: CN_ADJUST_DT 73 !......................................................................! 74 75 ! Initialize the function result. 76 ADJUSTDT = .FALSE. 77 USE_DT_PREV = .FALSE. 78 79 ! Steady-state simulation. 80 IF (DT==UNDEFINED .OR. DT<ZERO) RETURN 81 82 ! Local flag for adjusting the time step for CN implementation. 83 CN_ADJUST_DT = CN_ON .AND. ((RUN_TYPE=='NEW' .AND. NSTEP>1) .OR. & 84 (RUN_TYPE/='NEW' .AND. NSTEP >= (NSTEPRST+1))) 85 86 ! Stop sequential DT reductions by reseting the time-step and returning 87 ! control waiting for new user input. 88 IF(INTERACTIVE_MODE) & 89 CALL CHECK_TIMESTEP_FAIL_RATE(IER) 90 91 ! Iterate successfully converged. 92 !---------------------------------------------------------------------// 93 IF(IER == 0) THEN 94 95 ! Set back the timestep to original size which was halved previously for 96 ! 2nd order accurate time implementation. 97 IF(CN_ADJUST_DT) DT = 2.0D0*DT 98 99 ! Calculate a new DT every STEPS_MIN time steps. 100 IF(STEPS_TOT >= STEPS_MIN) THEN 101 NITOS_NEW = DBLE(NIT_TOT)/(STEPS_TOT*DT) 102 IF (NITOS_NEW > NITOS) DT_DIR = DT_DIR*(-1) 103 STEPS_TOT = 0 104 NITOS = NITOS_NEW 105 NIT_TOT = 0 106 IF (DT_DIR > 0) THEN 107 IF(NIT < MAX_NIT) DT = MIN(DT_MAX,DT/DT_FAC) 108 ELSE 109 DT = DT*DT_FAC 110 IF(PERSISTENT_MODE) DT = max(DT, DT_MIN) 111 ENDIF 112 113 ! DT was modified. Use the stored DT should be used to update TIME. 114 USE_DT_PREV = .TRUE. 115 116 ! Write the convergence stats to the screen/log file. 117 WRITE(ERR_MSG,"('DT=',g11.4,3x,'NIT/s=',A)") & 118 DT, trim(iVal(nint(NITOS))) 119 CALL FLUSH_ERR_MSG(HEADER=.FALSE., & 120 FOOTER=.FALSE., LOG=.FALSE.) 121 122 ELSE 123 STEPS_TOT = STEPS_TOT + 1 124 NIT_TOT = NIT_TOT + NIT 125 ENDIF 126 ! No need to iterate again 127 ADJUSTDT = .FALSE. 128 ! Cut the timestep into half for 2nd order accurate time implementation. 129 IF(CN_ADJUST_DT) DT = 0.5d0*DT 130 131 ! Iterate failed to converge. 132 !---------------------------------------------------------------------// 133 ELSE 134 135 ! Clear the error flag. 136 IER = 0 137 138 ! Reset the timestep to original size which was halved previously for 139 ! 2nd order accurate time implementation. 140 IF(CN_ADJUST_DT) DT = 2.0d0*DT 141 142 ! Reset counters. 143 STEPS_TOT = 0 144 NITOS = 0. 145 NIT_TOT = 0 146 147 ! Reduce the step size. 148 DT = DT*DT_FAC 149 150 ! The step size has decreased to the minimum. 151 IF (DT_FAC >= ONE) THEN 152 153 IF(PERSISTENT_MODE) THEN 154 ADJUSTDT = .FALSE. 155 ELSE 156 WRITE(ERR_MSG,"(3X,A)") & 157 'DT_FAC >= 1. Recovery not possible!' 158 CALL FLUSH_ERR_MSG(ABORT=.TRUE., & 159 HEADER=.FALSE., FOOTER=.FALSE.) 160 ENDIF 161 162 ELSEIF (DT > DT_MIN) THEN 163 164 IF(.NOT.INTERUPT) THEN 165 WRITE(ERR_MSG,"(3X,'Recovered: Dt=',G12.5,' :-)')") DT 166 CALL FLUSH_ERR_MSG(HEADER=.FALSE., FOOTER=.FALSE.) 167 ENDIF 168 169 CALL RESET_NEW 170 171 ! Iterate again with new dt 172 ADJUSTDT = .TRUE. 173 174 ! Cut the timestep for 2nd order accurate time implementation. 175 IF(CN_ADJUST_DT) DT = 0.5d0*DT 176 177 ! Set the return flag stop iterating. 178 ELSE 179 180 ! Prevent DT from dropping below DT_MIN. 181 IF(PERSISTENT_MODE) DT = max(DT, DT_MIN) 182 ADJUSTDT = .FALSE. 183 ENDIF 184 185 ENDIF 186 187 ! Update ONE/DT variable. 188 ODT = ONE/DT 189 190 ! Break out of the iterate loop if INTERUPT signal is given 191 IF(INTERUPT) ADJUSTDT = .FALSE. 192 193 RETURN 194 END FUNCTION ADJUSTDT 195 196 END MODULE ADJUST_DT 197