/[MITgcm]/MITgcm/tools/OAD_support/revolve.F90
ViewVC logotype

Diff of /MITgcm/tools/OAD_support/revolve.F90

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph | View Patch Patch

revision 1.1 by utke, Sat Feb 23 04:24:42 2013 UTC revision 1.3 by jmc, Fri May 17 20:57:12 2013 UTC
# Line 1  Line 1 
1    !> \mainpage
2    !! This is a Fortran9X adaptation of the functionality of Revolve; see Alg. 799 published as \cite Griewank2000ARA .
3    !! The interface of the routines differs from the cited revolve implementation
4    !! found in Adol-C and has been designed to be more in line with the
5    !! Fortran 9X language features. A minor extension is the  optional `bundle` parameter that allows to treat as many loop
6    !! iterations in one tape/adjoint sweep. If `bundle` is 1, the default, then the behavior is that of Alg. 799.
7    !!
8    !! The implementation (written by J. Utke)  is contained in revolve.f90, the use is illustrated in the `Examples` directory.
9    !!
10    !! The mercurial repository with the latest version can be found at:
11    !! <a href="http://mercurial.mcs.anl.gov/ad/RevolveF9X">http://mercurial.mcs.anl.gov/ad/RevolveF9X</a>
12    !!
13    
14    
15    !> the module containing the revolve implementation
16    !!
17  MODULE revolve  MODULE revolve
18    IMPLICIT NONE    IMPLICIT NONE
19    
20    PUBLIC :: rvInit, rvVerbose, rvNextAction, rvGuess, rvFactor, &    PUBLIC :: rvInit, rvVerbose, rvNextAction, rvGuess, rvFactor, &
21  rvStore, rvRestore, rvForward, rvFirstUTurn, rvUTurn, rvDone, rvError  rvStore, rvRestore, rvForward, rvFirstUTurn, rvUTurn, rvDone, rvError
22    
23    PRIVATE :: &    PRIVATE :: &
24  ourSteps, ourACP, ourCStart, ourCEnd, ourVerbosity, &  ourSteps, ourACP, ourCStart, ourCEnd, ourVerbosity, &
25  ourNumFwd , ourNumInv, ourNumStore, ourRWCP, ourPrevCEnd, ourFirstUTurned, &    ourNumFwd , ourNumInv, ourNumStore, ourRWCP, ourPrevCEnd, ourFirstUTurned, &
26  chkRange, forwdCount  chkRange, forwdCount
27    
28    ! possible actions    !> store a checkpoint now
29    INTEGER, PARAMETER :: rvStore      =1    !! equivalent to TAKESHOT in Alg. 799
30      INTEGER, PARAMETER :: rvStore      =1
31    
32      !> restore a checkpoint now
33      !! equivalent to RESTORE in Alg. 799
34    INTEGER, PARAMETER :: rvRestore    =2    INTEGER, PARAMETER :: rvRestore    =2
35    
36      !> execute iteration(s) forward
37      !! equivalent to ADVANCE in Alg. 799
38    INTEGER, PARAMETER :: rvForward    =3    INTEGER, PARAMETER :: rvForward    =3
39    
40      !> tape iteration(s); optionally leave to return later;  and (upon return) do the adjoint(s)
41      !! equivalent to FIRSTTURN in Alg. 799
42    INTEGER, PARAMETER :: rvFirstUTurn =4    INTEGER, PARAMETER :: rvFirstUTurn =4
43    
44      !> tape iteration(s) and do the adjoint(s)
45      !! equivalent to YOUTURN in Alg. 799
46    INTEGER, PARAMETER :: rvUTurn      =5    INTEGER, PARAMETER :: rvUTurn      =5
47    
48      !> we are done with adjoining the loop
49      !! equivalent to the `terminate` enum value in Alg. 799
50    INTEGER, PARAMETER :: rvDone       =6    INTEGER, PARAMETER :: rvDone       =6
51    
52      !> an error has occurred
53      !! equivalent to the `error` enum value in Alg. 799;
54      !! see also `errorMsg` in \ref rvAction
55    INTEGER, PARAMETER :: rvError      =7    INTEGER, PARAMETER :: rvError      =7
56    
57      !> this encapsulates all the information needed to perfrom the correct action
58      !! an instance is returned from \ref rvNextAction
59    TYPE rvAction    TYPE rvAction
60         !> the action that is to be implemented, termination, or error;
61         !! the value must be one of:
62         !! `rvStore`, `rvRestore`, `rvForward`,
63         !! `rvFirstUTurn`, `rvUTurn`, `rvDone`, `rvError`
64       INTEGER :: actionFlag = 0       INTEGER :: actionFlag = 0
65    
66         !> assumptions:
67         !! - the loop iterations are numbered in range [0,`ourSteps`-1]
68         !! - the model state is the input to the iteration numbered `startIteration`
69         !!
70         !! the interpretation is as follows based on the value of `actionFlag`:
71         !! - `rvForward`: execute iterations as the loop: `do currentIteration=startIteration, iteration-1`
72         !! - `rvRestore`: restores model state at `iteration` (here it has the same value as `startIteration`)
73         !! - `rvFirstUTurn`/`rvUTurn`: tape iterations in loop: do currentIteration=startIteration, iteration-1`
74         !!    followed by adjoint sweep over iterations in loop: do currentIteration=iteration-1,startIteration,-1
75         !!
76         !! for all other values of `actionFlag` the value of `iteration` is meaningless
77       INTEGER :: iteration  = 0       INTEGER :: iteration  = 0
78    
79         !> assuming the loop iterations are in [0,ourSteps-1] and `currentIteration` variable is maintained,
80         !! the interpretation is as follows based on the value of `actionFlag`:
81         !! - `rvForward`: execute iterations as the loop: `do currentIteration, iteration-1`
82         !! - `rvRestore`: set `currentIteration=iteration`
83         !!
84         !! for all other values of `actionFlag` the value of `iteration` is meaningless
85         INTEGER :: startIteration = 0
86    
87         !> the checkpoint number to be stored to restored
88         !! the value is meaninfull only if `actionFlag` is set to `rvStore` or `rvRestore`;
89         !!
90         !! This is approximately equivalent to `checks` in Alg. 799.
91       INTEGER :: cpNum      = 0       INTEGER :: cpNum      = 0
92       CHARACTER, dimension(80) :: errorMsg  
93         !> if an error has occurred `actionFlag` will be set to `rvError` and this will contain an error message
94         CHARACTER(80) :: errorMsg
95    END TYPE rvAction    END TYPE rvAction
96      
97      !> the number of iteration steps; set by calling \ref rvInit; not supposed to be set/used directly by the user;
98      !! note that the iterations are expected to range in [0, ourSteps-1];
99      !!
100      !! equivalent to `steps` in Alg. 799
101    INTEGER :: ourSteps    = 0 ! number of steps    INTEGER :: ourSteps    = 0 ! number of steps
102    INTEGER :: ourACP      = 0 ! allowed number of checkpoints  
103    INTEGER :: ourCStart   = 0 ! current subrange start    !> the number of iterations that may be bundled for a taping/adjoining sweep;
104    INTEGER :: ourCEnd     = 0 ! current subrange end    !! set by calling \ref rvInit; not supposed to be set/used directly by the user;
105    INTEGER :: ourNumFwd   = 0 ! count of forward steps    !!
106    INTEGER :: ourNumInv   = 0 ! count of invocations of rvNextAction    !! the default is 1 loop iteration which makes it equivalent to Alg. 799
107    INTEGER :: ourNumStore = 0 ! number of stored checkpoints    INTEGER :: ourBundle   = 1
108    INTEGER :: ourRWCP     = -1! checkpoint currently (re)stored (first checkpoint is 0)  
109    INTEGER :: ourPrevCEnd = 0 ! previous subrange end    !> the number of iterations in the last bundle
110    LOGICAL :: ourFirstUturned = .FALSE. ! have we first for the first time    !! set by calling \ref rvInit; not supposed to be set/used directly by the user;
111    ! vector of step numbers indexed by checkpoint    !!
112      !! the default is 1 (for `ourBundle` = 1)  which makes it equivalent to Alg. 799
113      INTEGER :: ourTail   = 1
114    
115      !> the number of checkpoints (ACP=AllowedCheckPoints) that can be stored at any time during the loop execution
116      !! set by calling \ref rvInit; not supposed to be set/used directly by the user
117      !!
118      !! equivalent to `snaps` in Alg. 799
119      INTEGER :: ourACP      = 0
120    
121      !> current subrange start;
122      !! not to be set/referemced directly by the user
123      !!
124      !! approximately equivalent to `capo` in Alg. 799
125      INTEGER :: ourCStart   = 0
126    
127      !> current subrange end;
128      !! not to be set/referemced directly by the user
129      !!
130      !! approximately equivalent to `fine` in Alg. 799
131      INTEGER :: ourCEnd     = 0
132    
133      !> count of the forward steps; diagnostic only
134      INTEGER :: ourNumFwd   = 0
135    
136      !> count of invocations to \ref rvNextAction ;  diagnostic only
137      INTEGER :: ourNumInv   = 0
138    
139      !> count of checkpoint stores; diagnostic only
140      INTEGER :: ourNumStore = 0
141    
142      !> checkpoint currently (re)stored - the first checkpoint is numbered 0;
143      !! not to be set/referemced directly by the user
144      INTEGER :: ourRWCP     = -1
145    
146      !> previous subrange end;
147      !! not to be set/referemced directly by the user
148      INTEGER :: ourPrevCEnd = 0
149    
150      !> have we first uturned already?;
151      !! not to be set/referemced directly by the user
152      LOGICAL :: ourFirstUturned = .FALSE.
153    
154      !> vector of step numbers indexed by checkpoint;
155      !! not to be set/referemced directly by the user
156    INTEGER, DIMENSION(:), ALLOCATABLE :: ourStepOf    INTEGER, DIMENSION(:), ALLOCATABLE :: ourStepOf
157    
158    ! for debugging purposes:    !> for debugging purposes; values imply:
159    ! 0 includes errors    !! - 0 includes errors
160    ! 1 includes summary info    !! - 1 includes summary info
161    ! 2 includes iterations with checkpoints stored    !! - 2 includes iterations with checkpoints stored
162    ! 3 includes all action results    !! - 3 includes all action results
163      !!
164      !! set via \ref rvVerbose
165    INTEGER :: ourVerbosity = 0    INTEGER :: ourVerbosity = 0
166    
167  CONTAINS  CONTAINS
168    
169  !--------------------------------------------------------------------*  !--------------------------------------------------------------------*
170    
171    FUNCTION rvInit(steps,checkpoints,errorMsg,anActionInstance)    !> method to initialize the internal state; must be called before any call to \ref rvNextAction
172      !! @param steps  the total number of steps in the iteration; equivalent to `steps` in Alg. 799
173      !! @param checkpoints the total number of checkpoints allowed to be stored at any time; equivalent to `snaps` in Alg. 799
174      !! @param errorMsg set when an error condition occurs; else set to `"none"`
175      !! @param anActionInstance  if supplied initializes its contents
176      !! @param bundle if supplied initializes `ourBundle`
177      !! @return `.true.` if successfull, else `.false.` ansd `errorMsg` will be set
178      FUNCTION rvInit(steps,checkpoints,errorMsg,anActionInstance,bundle)
179      IMPLICIT NONE      IMPLICIT NONE
180      LOGICAL :: rvInit      LOGICAL :: rvInit
181      INTEGER, INTENT(IN) :: steps      INTEGER, INTENT(IN) :: steps
182      INTEGER, INTENT(IN) :: checkpoints      INTEGER, INTENT(IN) :: checkpoints
183      CHARACTER ,dimension(:), INTENT(OUT) :: errorMsg      CHARACTER(*), INTENT(OUT) :: errorMsg
184      type(rvAction), optional :: anActionInstance      type(rvAction), optional :: anActionInstance
185      INTEGER :: predFwdCnt ! predicted forward count      INTEGER, INTENT(IN), optional :: bundle
186        INTEGER :: predFwdCnt ! predicted forward count
187      rvInit = .TRUE.      rvInit = .TRUE.
188      errorMsg ='none'      errorMsg ='none'
189      IF (present(anActionInstance)) THEN      IF (present(anActionInstance)) THEN
# Line 65  CONTAINS Line 192  CONTAINS
192         anActionInstance%iteration  = 0         anActionInstance%iteration  = 0
193         anActionInstance%cpNum      = 0         anActionInstance%cpNum      = 0
194      END IF      END IF
195      IF (steps<0 .OR. checkpoints<0) THEN      IF (present(bundle)) THEN
196           ourBundle = bundle
197        END IF
198        IF (ourBundle<1 .OR. ourBundle>steps) THEN
199           rvInit=.FALSE.
200           errorMsg = "revolve::rvInit: bundle parameter out of range [1,steps]"
201        ELSEIF (steps<0) THEN
202         rvInit=.FALSE.         rvInit=.FALSE.
203         errorMsg = 'revolve::rvInit: negative steps or checkpoints'         errorMsg = 'revolve::rvInit: negative steps'
204      ELSE      ELSEIF (checkpoints<0) THEN
205           rvInit=.FALSE.
206           errorMsg = 'revolve::rvInit: negative checkpoints'
207        ELSE
208         ourCStart       = 0         ourCStart       = 0
209         ourSteps        = steps         ourSteps        = steps
210         ourCEnd         = steps         IF (ourBundle .gt. 1) THEN
211              ourTail=modulo(ourSteps,ourBundle)
212              ourSteps=ourSteps/ourBundle
213              IF (ourTail>0) THEN
214                 ourSteps=ourSteps+1
215              ELSE
216                 ourTail=ourBundle
217              END IF
218           END IF
219           ourCEnd         = ourSteps
220         ourACP          = checkpoints         ourACP          = checkpoints
221         ourNumFwd       = 0         ourNumFwd       = 0
222         ourNumInv       = 0         ourNumInv       = 0
223         ourNumStore     = 0         ourNumStore     = 0
224         ourRWCP         = -1         ourRWCP         = -1
225         ourPrevCEnd     = 0         ourPrevCEnd     = 0
226         ourFirstUTurned = .FALSE.         ourFirstUTurned = .FALSE.
227    
228         IF (ALLOCATED(ourStepOf)) THEN         IF (ALLOCATED(ourStepOf)) THEN
# Line 88  CONTAINS Line 233  CONTAINS
233         END IF         END IF
234    
235         IF (ourVerbosity>0) THEN         IF (ourVerbosity>0) THEN
236            predFwdCnt = forwdCount(ourCEnd-ourCStart,ourACP)            predFwdCnt = forwdCount(steps,ourACP,ourBundle)
237            IF (predFwdCnt==-1) THEN            IF (predFwdCnt==-1) THEN
238               errorMsg='error in forwdCount'               errorMsg='revolve::rvInit: error returned by  revolve::forwdCount'
239                 rvInit=.FALSE.
240               RETURN               RETURN
241            ELSE            ELSE
242               WRITE (*,'(A)') 'prediction:'               WRITE (*,'(A)') 'prediction:'
243               WRITE (*,'(A,I7)') ' needed forward steps: ', predFwdCnt               WRITE (*,'(A,I7)')   ' overhead forward steps : ', predFwdCnt
244               WRITE (*,'(A,F8.4)') ' slowdown factor     : ', dble(predFwdCnt)/(ourCEnd-ourCStart)               WRITE (*,'(A,F8.4)') ' overhead factor        : ', dble(predFwdCnt)/(steps)
245            END IF            END IF
246         END IF         END IF
247      END IF      END IF
# Line 103  CONTAINS Line 249  CONTAINS
249    
250  !--------------------------------------------------------------------*  !--------------------------------------------------------------------*
251    
252      !> method to set the verbosity to a level in [0-3] as described for `ourVerbosity`
253    SUBROUTINE rvVerbose(level)    SUBROUTINE rvVerbose(level)
254      IMPLICIT NONE      IMPLICIT NONE
255      INTEGER, INTENT(IN) :: level      INTEGER, INTENT(IN) :: level
256      ourVerbosity=level      ourVerbosity=level
257    END SUBROUTINE rvVerbose    END SUBROUTINE rvVerbose
258    
259  !--------------------------------------------------------------------*  !--------------------------------------------------------------------*
260      !> the method to determine the next action; to be called in an unbound loop after \ref rvInit
261      !! @return an instance of `rvAction` set to describe the next action (see the member documentation);
262      !!
263      !! this method modifies the internal state; it is approximately equivalent to the method `revolve` in Alg. 799
264    FUNCTION rvNextAction()    FUNCTION rvNextAction()
265      IMPLICIT NONE      IMPLICIT NONE
266      REAL :: bino1, bino2, bino3, bino4, bino5      REAL :: bino1, bino2, bino3, bino4, bino5
267      INTEGER :: availCP    ! available checkpoint slots  
268      INTEGER :: prevCStart ! previous subrange start      !> available checkpoint slots
269      INTEGER :: range      !      INTEGER :: availCP
270    
271        !> local copy of previous subrange start
272        INTEGER :: prevCStart
273    
274        INTEGER :: range
275      INTEGER :: reps      INTEGER :: reps
276      INTEGER :: i      INTEGER :: i
277        INTEGER :: ourRWCPinBd
278      type(rvAction) :: rvNextAction      type(rvAction) :: rvNextAction
279      IF (ourNumInv==0) THEN      IF (ourNumInv==0) THEN
280         ! first invocation         ! first invocation
# Line 127  CONTAINS Line 283  CONTAINS
283         END DO         END DO
284         ourStepOf(0) = ourCStart - 1         ourStepOf(0) = ourCStart - 1
285      END IF      END IF
286        prevCStart = ourCStart
287      ourNumInv = ourNumInv + 1      ourNumInv = ourNumInv + 1
288        ! make sure ourRWCPinBd stay within bounds of array ourStepOf:
289        ourRWCPinBd = MIN( MAX( ourRWCP, 0 ), ourACP )
290      IF ((ourCEnd-ourCStart)==0) THEN      IF ((ourCEnd-ourCStart)==0) THEN
291         ! nothing in current subrange         ! nothing in current subrange
292         IF ((ourRWCP==(-1)) .OR. (ourCStart==ourStepOf(0))) THEN         IF ((ourRWCP==(-1)) .OR. (ourCStart==ourStepOf(0))) THEN
293            ! we are done            ! we are done
294            ourRWCP = ourRWCP - 1            ourRWCP = ourRWCP - 1
295              IF (ourVerbosity>2) THEN
296                 WRITE (*,FMT='(A)') ' done'
297              END IF
298            IF (ourVerbosity>0) THEN            IF (ourVerbosity>0) THEN
299               WRITE (*,'(A)') 'summary:'               WRITE (*,'(A)') 'summary:'
300               WRITE (*,'(A,I8)') ' forward steps:', ourNumFwd               WRITE (*,'(A,I8)') ' overhead forward steps:', ourNumFwd
301               WRITE (*,'(A,I8)') ' CP stores    :', ourNumStore               WRITE (*,'(A,I8)') ' CP stores             :', ourNumStore
302               WRITE (*,'(A,I8)') ' invocations  :', ourNumInv               WRITE (*,'(A,I8)') ' rvNextAction calls    :', ourNumInv
303            END IF            END IF
304            rvNextAction%actionFlag = rvDone            rvNextAction%actionFlag = rvDone
305          ELSE          ELSE
306             ourCStart = ourStepOf(ourRWCP)             ourCStart = ourStepOf(ourRWCP)
307             ourPrevCEnd = ourCEnd             ourPrevCEnd = ourCEnd
308             rvNextAction%actionFlag = rvRestore             rvNextAction%actionFlag = rvRestore
309          END IF          END IF
310       ELSE IF ((ourCEnd-ourCStart)==1) THEN       ELSE IF ((ourCEnd-ourCStart)==1) THEN
311          ourCEnd = ourCEnd - 1          ourCEnd = ourCEnd - 1
# Line 155  CONTAINS Line 317  CONTAINS
317          ELSE          ELSE
318             rvNextAction%actionFlag = rvUTurn             rvNextAction%actionFlag = rvUTurn
319          END IF          END IF
320       ELSE IF ((ourRWCP==(-1)) .OR. (ourStepOf(ourRWCP)/=ourCStart)) THEN       ELSE IF ((ourRWCP==(-1)) .OR. (ourStepOf(ourRWCPinBd)/=ourCStart)) THEN
321          ourRWCP = ourRWCP + 1          ourRWCP = ourRWCP + 1
322          IF (ourRWCP+1>ourACP) THEN          IF (ourRWCP+1>ourACP) THEN
323             rvNextAction%actionFlag = rvError             rvNextAction%actionFlag = rvError
324             rvNextAction%errorMsg='insufficient allowed checkpoints'             rvNextAction%errorMsg='revolve::rvNextAction: insufficient allowed checkpoints'
325             RETURN             RETURN
326          ELSE          ELSE
327             ourStepOf(ourRWCP) = ourCStart             ourStepOf(ourRWCP) = ourCStart
# Line 169  CONTAINS Line 331  CONTAINS
331          END IF          END IF
332       ELSE IF ((ourPrevCEnd<ourCEnd) .AND. (ourACP==ourRWCP+1)) THEN       ELSE IF ((ourPrevCEnd<ourCEnd) .AND. (ourACP==ourRWCP+1)) THEN
333          rvNextAction%actionFlag = rvError          rvNextAction%actionFlag = rvError
334          rvNextAction%errorMsg='insufficient allowed checkpoints'          rvNextAction%errorMsg='revolve::rvNextAction: insufficient allowed checkpoints'
335       ELSE       ELSE
         prevCStart = ourCStart  
336          availCP = ourACP - ourRWCP          availCP = ourACP - ourRWCP
337          IF (availCP<1) THEN          IF (availCP<1) THEN
338             rvNextAction%actionFlag = rvError             rvNextAction%actionFlag = rvError
339             rvNextAction%errorMsg='insufficient allowed checkpoints'             rvNextAction%errorMsg='revolve::rvNextAction: insufficient allowed checkpoints'
340          ELSE          ELSE
341             reps = 0             reps = 0
342             range = 1             range = 1
# Line 214  CONTAINS Line 375  CONTAINS
375            IF (ourCStart==prevCStart) THEN            IF (ourCStart==prevCStart) THEN
376              ourCStart = prevCStart + 1              ourCStart = prevCStart + 1
377            END IF            END IF
378            ourNumFwd = ourNumFwd + ourCStart - prevCStart            IF (ourCStart==ourSteps) THEN
379                 ourNumFwd = ourNumFwd + ((ourCStart-1) - prevCStart)*ourBundle + ourTail
380              ELSE
381                 ourNumFwd = ourNumFwd + (ourCStart - prevCStart)*ourBundle
382              END IF
383            rvNextAction%actionFlag = rvForward            rvNextAction%actionFlag = rvForward
384          END IF          END IF
385        END IF        END IF
386        rvNextAction%iteration=ourCStart        rvNextAction%startIteration=prevCStart*ourBundle
387        IF (rvNextAction%actionFlag /= rvError .AND. rvNextAction%actionFlag /= rvDone) THEN        IF (rvNextAction%actionFlag==rvFirstUTurn) THEN
388             rvNextAction%iteration=(ourCStart)*ourBundle+ourTail
389          ELSE IF (rvNextAction%actionFlag==rvUTurn) THEN
390             rvNextAction%iteration=(ourCStart+1)*ourBundle
391          ELSE
392             rvNextAction%iteration=(ourCStart)*ourBundle
393          END IF
394          IF (rvNextAction%actionFlag /= rvError) THEN
395           IF (ourVerbosity>2) THEN           IF (ourVerbosity>2) THEN
396              SELECT CASE( rvNextAction%actionFlag)              SELECT CASE( rvNextAction%actionFlag)
397              CASE (rvForward)              CASE (rvForward)
398                 WRITE (*,FMT='(A)',ADVANCE='NO') ' forward to  :'                 WRITE (*,FMT='(A,I8,A,I8,A)') ' run forward iterations    [', &
399                   rvNextAction%startIteration, ',', rvNextAction%iteration-1,']'
400              CASE (rvRestore)              CASE (rvRestore)
401                 WRITE (*,FMT='(A)',ADVANCE='NO') ' restore at  :'                 WRITE (*,FMT='(A,I8)')        ' restore input of iteration ',&
402                   rvNextAction%iteration
403              CASE (rvFirstUTurn)              CASE (rvFirstUTurn)
404                 WRITE (*,FMT='(A)',ADVANCE='NO') ' 1st uturn at:'                 WRITE (*,FMT='(A,I8,A,I8,A)') ' 1st uturn for iterations  [',&
405              CASE(rvUTurn)                       rvNextAction%startIteration, ',', rvNextAction%iteration-1,']'
406                 WRITE (*,FMT='(A)',ADVANCE='NO') ' uturn at    :'              CASE(rvUTurn)
407                   WRITE (*,FMT='(A,I8,A,I8,A)') ' uturn for iterations      [',&
408                   rvNextAction%startIteration, ',', rvNextAction%iteration-1,']'
409              END SELECT              END SELECT
410           END IF           END IF
411           IF (ourVerbosity>1) THEN           IF ((ourVerbosity>1) .AND. (rvNextAction%actionFlag == rvStore)) THEN
412              IF (rvNextAction%actionFlag == rvStore) THEN                  WRITE (*,FMT='(A,I8)')        ' store input of iteration   ',&
413                 WRITE (*,FMT='(A)',ADVANCE='NO') ' store at    :'                  rvNextAction%iteration
             END IF  
             WRITE (*,'(I8)') rvNextAction%iteration  
414           END IF           END IF
415        END IF        END IF
416        rvNextAction%cpNum=ourRWCP        rvNextAction%cpNum=ourRWCP
417      END FUNCTION rvNextAction      END FUNCTION rvNextAction
418    
419  !--------------------------------------------------------------------*  !--------------------------------------------------------------------*
420        !> estimates the number of checkpoints required; equivalent to `adjust` in Alg. 799
421      FUNCTION rvGuess(steps)      !! @param steps is the number of iterations
422        !! @param bundle is optional; detaults to 1, if specified indicates the number of iterations bundled in one tape/adjoint sweep
423        !! @return the number of checkpoints such that the growth in spatial complexity is balanced with the  growth in temporal complexity
424        !!
425        !! this method does not change the internal state and does not require \ref rvInit
426        FUNCTION rvGuess(steps,bundle)
427      IMPLICIT NONE      IMPLICIT NONE
428        INTEGER :: steps        INTEGER, INTENT(IN) :: steps, bundle
429        INTEGER :: reps, s, checkpoints        OPTIONAL :: bundle
430          INTEGER :: reps, s, checkpoints, b, tail, bSteps
431        INTEGER :: rvGuess        INTEGER :: rvGuess
432        checkpoints = 1        b=1
433        reps = 1        bSteps=steps
434        s = 0        IF (present(bundle)) THEN
435        DO WHILE (chkRange(checkpoints+s,reps+s)>steps)           b=bundle
436          s = s - 1        END IF
437        END DO        IF (steps<1) THEN
438        DO WHILE (chkRange(checkpoints+s,reps+s)<steps)          WRITE (*,fmt=*) 'revolve::rvGuess: error: steps < 1'
439          s = s + 1          rvGuess = -1
440        END DO        ELSE IF (b<1) THEN
441        checkpoints = checkpoints + s          WRITE (*,fmt=*) 'revolve::rvGuess: error: bundle < 1'
442        reps = reps + s          rvGuess = -1
443        s = -1        ELSE
444        DO WHILE (chkRange(checkpoints,reps)>=steps)          IF (b .gt. 1) THEN
445          IF (checkpoints>reps) THEN            tail=modulo(bSteps,b)
446            checkpoints = checkpoints - 1            bSteps=bSteps/b
447            s = 0            IF (tail>0) THEN
448                bSteps=bSteps+1
449              END IF
450            END IF
451            IF (bSteps==1) THEN
452              rvGuess=0
453          ELSE          ELSE
454            reps = reps - 1            checkpoints = 1
455            s = 1            reps = 1
456              s = 0
457              DO WHILE (chkRange(checkpoints+s,reps+s)>bSteps)
458                s = s - 1
459              END DO
460              DO WHILE (chkRange(checkpoints+s,reps+s)<bSteps)
461                s = s + 1
462              END DO
463              checkpoints = checkpoints + s
464              reps = reps + s
465              s = -1
466              DO WHILE (chkRange(checkpoints,reps)>=bSteps)
467                IF (checkpoints>reps) THEN
468                  checkpoints = checkpoints - 1
469                  s = 0
470                ELSE
471                  reps = reps - 1
472                  s = 1
473                END IF
474              END DO
475              IF (s==0) THEN
476                checkpoints = checkpoints + 1
477              END IF
478              IF (s==1) reps = reps + 1
479              rvGuess = checkpoints
480          END IF          END IF
       END DO  
       IF (s==0) THEN  
         checkpoints = checkpoints + 1  
481        END IF        END IF
       IF (s==1) reps = reps + 1  
       rvGuess = checkpoints  
482      END FUNCTION rvGuess      END FUNCTION rvGuess
483    
484  !--------------------------------------------------------------------*  !--------------------------------------------------------------------*
485        !> computes the run time overhead factor; equivalent to `expense` in Alg. 799
486      FUNCTION rvFactor(steps,checkpoints)      !! @param steps is the number of iterations
487        !! @param checkpoints is the number of allowed checkpoints
488        !! @param bundle is optional; detaults to 1, if specified indicates the number of iterations bundled in one tape/adjoint sweep
489        !! @return the estimated runtime overhead factor (does not account for the time needed to write checkpoints)
490        !!
491        !! this method does not change the internal state and does not require \ref rvInit
492        FUNCTION rvFactor(steps,checkpoints,bundle)
493      IMPLICIT NONE      IMPLICIT NONE
494        INTEGER :: checkpoints, steps        INTEGER, INTENT(IN) :: checkpoints, steps, bundle
495          OPTIONAL :: bundle
496          INTEGER :: b, f
497        DOUBLE PRECISION :: rvFactor        DOUBLE PRECISION :: rvFactor
498        IF (checkpoints<1) THEN        b=1
499          WRITE (*,fmt=*) 'error occurs in RVFACTOR: CHECKPOINTS < 1'        IF (present(bundle)) THEN
500          rvFactor = -1           b=bundle
501        ELSE IF (checkpoints<1) THEN        END IF
502          WRITE (*,fmt=*) 'error occurs in RVFACTOR: CHECKPOINTS < 1'        f=forwdCount(steps,checkpoints,b)
503          rvFactor = -1        IF (f==-1)  THEN
504            WRITE (*,fmt=*) 'revolve::rvFactor: error returned by  revolve::forwdCount'
505            rvFactor=-1
506        ELSE        ELSE
507          rvFactor = dble(forwdCount(steps,checkpoints))          rvFactor = dble(f)/steps
         IF (rvFactor/=-1) rvFactor = rvFactor/steps  
508        END IF        END IF
509      END FUNCTION rvFactor      END FUNCTION rvFactor
510    
511  !--------------------------------------------------------------------*  !--------------------------------------------------------------------*
512        !> internal method not to be referenced by the user
513      FUNCTION chkRange(ss,tt)      FUNCTION chkRange(ss,tt)
514      IMPLICIT NONE      IMPLICIT NONE
515        INTEGER :: ss, tt        INTEGER :: ss, tt
# Line 305  CONTAINS Line 518  CONTAINS
518        INTEGER :: chkRange        INTEGER :: chkRange
519        res = 1.        res = 1.
520        IF (tt<0 .OR. ss<0) THEN        IF (tt<0 .OR. ss<0) THEN
521          WRITE (*,fmt=*) 'error in MAXRANGE: negative parameter '          WRITE (*,fmt=*) 'revolve::chkRange: error: negative parameter '
522          chkRange = -1          chkRange = -1
523        ELSE        ELSE
524          DO i = 1, tt          DO i = 1, tt
# Line 317  CONTAINS Line 530  CONTAINS
530            chkRange = res            chkRange = res
531          ELSE          ELSE
532            chkRange = 2.0D0**31 - 3            chkRange = 2.0D0**31 - 3
533            WRITE (*,fmt=*) 'warning from  MAXRANGE: returned maximal integer'            WRITE (*,fmt=*) 'revolve::chkRange: warning: returning maximal integer ',&
534            WRITE (*,fmt=*) chkRange            chkRange
535          END IF          END IF
536        END IF        END IF
537      END FUNCTION chkRange      END FUNCTION chkRange
538    
539  !--------------------------------------------------------------------*  !--------------------------------------------------------------------*
540    
541      FUNCTION forwdCount(steps,checkpoints)      !> internal method not to be referenced by the user;
542        !> predicts the  number of recomputation-from-checkpoint forwards steps (overhead)
543        FUNCTION forwdCount(steps,checkpoints,bundle)
544      IMPLICIT NONE      IMPLICIT NONE
545        INTEGER :: checkpoints, steps        INTEGER, INTENT(IN) :: checkpoints, steps, bundle
546        INTEGER :: range, reps        INTEGER :: range, reps,s,tail
547        INTEGER :: forwdCount        INTEGER :: forwdCount
548        IF (checkpoints<1) THEN        IF (checkpoints<0) THEN
549            WRITE (*,fmt=*) 'revolve::forwdCount: error: checkpoints < 0'
550            forwdCount = -1
551          ELSE IF (steps<1) THEN
552            WRITE (*,fmt=*) 'revolve::forwdCount: error: steps < 1'
553            forwdCount = -1
554          ELSE IF (bundle<1) THEN
555            WRITE (*,fmt=*) 'revolve::forwdCount: error: bundle < 1'
556          forwdCount = -1          forwdCount = -1
557        ELSE        ELSE
558          reps = 0          s=steps
559          range = 1          IF (bundle .gt. 1) THEN
560          DO WHILE (range<steps)            tail=modulo(s,bundle)
561            reps = reps + 1            s=s/bundle
562            range = range*(reps+checkpoints)/reps            IF (tail>0) THEN
563          END DO              s=s+1
564          forwdCount = reps*steps - range*reps/(checkpoints+1)            END IF
565            END IF
566            IF (s==1) THEN
567              forwdCount = 0
568            ELSE IF (checkpoints==0) THEN
569              WRITE (*,fmt=*) &
570              'revolve::forwdCount: error: given inputs require checkpoints>0'
571              forwdCount = -1
572            ELSE
573              reps = 0
574              range = 1
575              DO WHILE (range<s)
576                reps = reps + 1
577                range = range*(reps+checkpoints)/reps
578              END DO
579              forwdCount = (reps*s - range*reps/(checkpoints+1))*bundle
580            END IF
581        END IF        END IF
582      END FUNCTION forwdCount      END FUNCTION forwdCount
583    

Legend:
Removed from v.1.1  
changed lines
  Added in v.1.3

  ViewVC Help
Powered by ViewVC 1.1.22