SICOPOLIS V5-dev  Revision 1264
revolve.f90
Go to the documentation of this file.
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
18  IMPLICIT NONE
19 
20  PUBLIC :: rvinit, rvverbose, rvnextaction, &
21 rvguess, rvfactor, &
24 rverror, rvadjust
25 
26  PRIVATE :: &
27 oursteps, ouracp, ourcstart, ourcend, ourverbosity, &
28 ournumfwd , ournuminv, ournumstore, ourrwcp, ourprevcend, &
29 ourfirstuturned, chkrange, forwdcount
30 
31  !> store a checkpoint now
32  !! equivalent to TAKESHOT in Alg. 799
33  INTEGER, PARAMETER :: rvstore =1
34 
35  !> restore a checkpoint now
36  !! equivalent to RESTORE in Alg. 799
37  INTEGER, PARAMETER :: rvrestore =2
38 
39  !> execute iteration(s) forward
40  !! equivalent to ADVANCE in Alg. 799
41  INTEGER, PARAMETER :: rvforward =3
42 
43  !> tape iteration(s); optionally leave to return later; and (upon return) do the adjoint(s)
44  !! equivalent to FIRSTTURN in Alg. 799
45  INTEGER, PARAMETER :: rvfirstuturn =4
46 
47  !> tape iteration(s) and do the adjoint(s)
48  !! equivalent to YOUTURN in Alg. 799
49  INTEGER, PARAMETER :: rvuturn =5
50 
51  !> we are done with adjoining the loop
52  !! equivalent to the `terminate` enum value in Alg. 799
53  INTEGER, PARAMETER :: rvdone =6
54 
55  !> an error has occurred
56  !! equivalent to the `error` enum value in Alg. 799;
57  !! see also `errorMsgRevolve` in \ref rvAction
58  INTEGER, PARAMETER :: rverror =7
59 
60  !> this encapsulates all the information needed to perfrom the correct action
61  !! an instance is returned from \ref rvNextAction
62  TYPE rvaction
63  !> the action that is to be implemented, termination, or error;
64  !! the value must be one of:
65  !! `rvStore`, `rvRestore`, `rvForward`,
66  !! `rvFirstUTurn`, `rvUTurn`, `rvDone`, `rvError`
67  INTEGER :: actionflag = 0
68 
69  !> assumptions:
70  !! - the loop iterations are numbered in range [0,`ourSteps`-1]
71  !! - the model state is the input to the iteration numbered `startIteration`
72  !!
73  !! the interpretation is as follows based on the value of `actionFlag`:
74  !! - `rvForward`: execute iterations as the loop: `do currentIteration=startIteration, iteration-1`
75  !! - `rvRestore`: restores model state at `iteration` (here it has the same value as `startIteration`)
76  !! - `rvFirstUTurn`/`rvUTurn`: tape iterations in loop: do currentIteration=startIteration, iteration-1`
77  !! followed by adjoint sweep over iterations in loop: do currentIteration=iteration-1,startIteration,-1
78  !!
79  !! for all other values of `actionFlag` the value of `iteration` is meaningless
80  INTEGER :: iteration = 0
81 
82  !> assuming the loop iterations are in [0,ourSteps-1] and `currentIteration` variable is maintained,
83  !! the interpretation is as follows based on the value of `actionFlag`:
84  !! - `rvForward`: execute iterations as the loop: `do currentIteration, iteration-1`
85  !! - `rvRestore`: set `currentIteration=iteration`
86  !!
87  !! for all other values of `actionFlag` the value of `iteration` is meaningless
88  INTEGER :: startiteration = 0
89 
90  !> the checkpoint number to be stored to restored
91  !! the value is meaninfull only if `actionFlag` is set to `rvStore` or `rvRestore`;
92  !!
93  !! This is approximately equivalent to `checks` in Alg. 799.
94  INTEGER :: cpnum = 0
95 
96  !> if an error has occurred `actionFlag` will be set to `rvError` and this will contain an error message
97  CHARACTER(80) :: errormsgrevolve
98  END TYPE rvaction
99 
100  !> the number of iteration steps; set by calling \ref rvInit; not supposed to be set/used directly by the user;
101  !! note that the iterations are expected to range in [0, ourSteps-1];
102  !!
103  !! equivalent to `steps` in Alg. 799
104  INTEGER :: oursteps = 0 ! number of steps
105 
106  !> the number of iterations that may be bundled for a taping/adjoining sweep;
107  !! set by calling \ref rvInit; not supposed to be set/used directly by the user;
108  !!
109  !! the default is 1 loop iteration which makes it equivalent to Alg. 799
110  INTEGER :: ourbundle = 1
111 
112  !> the number of iterations in the last bundle
113  !! set by calling \ref rvInit; not supposed to be set/used directly by the user;
114  !!
115  !! the default is 1 (for `ourBundle` = 1) which makes it equivalent to Alg. 799
116  INTEGER :: ourtail = 1
117 
118  !> the number of checkpoints (ACP=AllowedCheckPoints) that can be stored at any time during the loop execution
119  !! set by calling \ref rvInit; not supposed to be set/used directly by the user
120  !!
121  !! equivalent to `snaps` in Alg. 799
122  INTEGER :: ouracp = 0
123 
124  !> current subrange start;
125  !! not to be set/referemced directly by the user
126  !!
127  !! approximately equivalent to `capo` in Alg. 799
128  INTEGER :: ourcstart = 0
129 
130  !> current subrange end;
131  !! not to be set/referemced directly by the user
132  !!
133  !! approximately equivalent to `fine` in Alg. 799
134  INTEGER :: ourcend = 0
135 
136  !> count of the forward steps; diagnostic only
137  INTEGER :: ournumfwd = 0
138 
139  !> count of invocations to \ref rvNextAction ; diagnostic only
140  INTEGER :: ournuminv = 0
141 
142  !> count of checkpoint stores; diagnostic only
143  INTEGER :: ournumstore = 0
144 
145  !> checkpoint currently (re)stored - the first checkpoint is numbered 0;
146  !! not to be set/referemced directly by the user
147  INTEGER :: ourrwcp = -1
148 
149  !> previous subrange end;
150  !! not to be set/referemced directly by the user
151  INTEGER :: ourprevcend = 0
152 
153  !> have we first uturned already?;
154  !! not to be set/referemced directly by the user
155  LOGICAL :: ourfirstuturned = .false.
156 
157  !> vector of step numbers indexed by checkpoint;
158  !! not to be set/referemced directly by the user
159  INTEGER, DIMENSION(:), ALLOCATABLE :: ourstepof
160 
161  !> for debugging purposes; values imply:
162  !! - 0 includes errors
163  !! - 1 includes summary info
164  !! - 2 includes iterations with checkpoints stored
165  !! - 3 includes all action results
166  !!
167  !! set via \ref rvVerbose
168  INTEGER :: ourverbosity = 0
169 
170 CONTAINS
171 
172 !--------------------------------------------------------------------*
173 
174  !> method to initialize the internal state; must be called before any call to \ref rvNextAction
175  !! @param steps the total number of steps in the iteration; equivalent to `steps` in Alg. 799
176  !! @param checkpoints the total number of checkpoints allowed to be stored at any time; equivalent to `snaps` in Alg. 799
177  !! @param errorMsgRevolve set when an error condition occurs; else set to `"none"`
178  !! @param anActionInstance if supplied initializes its contents
179  !! @param bundle if supplied initializes `ourBundle`
180  !! @return `.true.` if successfull, else `.false.` ansd `errorMsgRevolve` will be set
181  FUNCTION rvinit(steps,checkpoints,errorMsgRevolve,anActionInstance,bundle)
182  IMPLICIT NONE
183  LOGICAL :: rvInit
184  INTEGER, INTENT(IN) :: steps
185  INTEGER, INTENT(IN) :: checkpoints
186  CHARACTER(*), INTENT(OUT) :: errorMsgRevolve
187  type(rvaction), optional :: anActionInstance
188  INTEGER, INTENT(IN), optional :: bundle
189  INTEGER :: predFwdCnt ! predicted forward count
190  rvinit = .true.
191  errormsgrevolve ='none'
192  IF (present(anactioninstance)) THEN
193  ! same as default init above
194  anactioninstance%actionFlag = 0
195  anactioninstance%iteration = 0
196  anactioninstance%cpNum = 0
197  END IF
198  IF (present(bundle)) THEN
199  ourbundle = bundle
200  END IF
201  IF (ourbundle<1 .OR. ourbundle>steps) THEN
202  rvinit=.false.
203  print *, "ERROR:: ourBundle is ", ourbundle, " steps is ", steps
204  errormsgrevolve = "revolve::rvInit: bundle parameter out of range [1,steps]"
205  ELSEIF (steps<0) THEN
206  rvinit=.false.
207  errormsgrevolve = 'revolve::rvInit: negative steps'
208  ELSEIF (checkpoints<0) THEN
209  rvinit=.false.
210  errormsgrevolve = 'revolve::rvInit: negative checkpoints'
211  ELSE
212  ourcstart = 0
213  oursteps = steps
214  IF (ourbundle .gt. 1) THEN
215  ourtail=modulo(oursteps,ourbundle)
216  oursteps=oursteps/ourbundle
217  IF (ourtail>0) THEN
218  oursteps=oursteps+1
219  ELSE
221  END IF
222  END IF
223  ourcend = oursteps
224  ouracp = checkpoints
225  ournumfwd = 0
226  ournuminv = 0
227  ournumstore = 0
228  ourrwcp = -1
229  ourprevcend = 0
230  ourfirstuturned = .false.
231 
232  IF (ALLOCATED(ourstepof)) THEN
233  DEALLOCATE(ourstepof)
234  END IF
235  IF(.NOT.ALLOCATED(ourstepof)) THEN
236  ALLOCATE(ourstepof(0:ouracp))
237  END IF
238 
239  IF (ourverbosity>0) THEN
240  predfwdcnt = forwdcount(steps,ouracp,ourbundle)
241  IF (predfwdcnt==-1) THEN
242  errormsgrevolve='revolve::rvInit: error returned by revolve::forwdCount'
243  rvinit=.false.
244  RETURN
245  ELSE
246  WRITE (*,'(A)') 'prediction:'
247  WRITE (*,'(A,I7)') ' overhead forward steps : ', predfwdcnt
248  WRITE (*,'(A,F8.4)') ' overhead factor : ', dble(predfwdcnt)/(steps)
249  END IF
250  END IF
251  END IF
252  END FUNCTION rvinit
253 
254 !--------------------------------------------------------------------*
255 
256  !> method to change the internal state for the total number of steps/checkpoints; must be called after \ref rvInit
257  !! @param steps the total number of steps in the iteration; equivalent to `steps` in Alg. 799
258  !! @param errorMsgRevolve set when an error condition occurs; else set to `"none"`
259  !! @return `.true.` if successfull, else `.false.` ansd `errorMsgRevolve` will be set
260  FUNCTION rvadjust(steps,checkpoints,errorMsgRevolve)
261  IMPLICIT NONE
262  LOGICAL :: rvAdjust
263  INTEGER, INTENT(IN) :: steps
264  INTEGER, INTENT(IN) :: checkpoints
265  CHARACTER(*), INTENT(OUT) :: errorMsgRevolve
266  rvadjust=.false.
267  END FUNCTION
268 
269 !--------------------------------------------------------------------*
270 
271  !> method to set the verbosity to a level in [0-3] as described for `ourVerbosity`
272  SUBROUTINE rvverbose(level)
273  IMPLICIT NONE
274  INTEGER, INTENT(IN) :: level
275  ourverbosity=level
276  END SUBROUTINE rvverbose
277 
278 !--------------------------------------------------------------------*
279  !> the method to determine the next action; to be called in an unbound loop after \ref rvInit
280  !! @return an instance of `rvAction` set to describe the next action (see the member documentation);
281  !!
282  !! this method modifies the internal state; it is approximately equivalent to the method `revolve` in Alg. 799
283  FUNCTION rvnextaction()
284  IMPLICIT NONE
285  REAL :: bino1, bino2, bino3, bino4, bino5
286 
287  !> available checkpoint slots
288  INTEGER :: availCP
289 
290  !> local copy of previous subrange start
291  INTEGER :: prevCStart
292 
293  INTEGER :: range
294  INTEGER :: reps
295  INTEGER :: i
296  LOGICAL :: rwcpTest
297  type(rvaction) :: rvNextAction
298  IF (ournuminv==0) THEN
299  ! first invocation
300  DO i = 0, ouracp
301  ourstepof(i) = 0
302  END DO
303  ourstepof(0) = ourcstart - 1
304  END IF
305  prevcstart = ourcstart
306  ournuminv = ournuminv + 1
307  rwcptest=(ourrwcp==(-1))
308  IF (.not. rwcptest) THEN
309  rwcptest=(ourstepof(ourrwcp)/=ourcstart)
310  END IF
311  IF ((ourcend-ourcstart)==0) THEN
312  ! nothing in current subrange
313  IF ((ourrwcp==(-1)) .OR. (ourcstart==ourstepof(0))) THEN
314  ! we are done
315  ourrwcp = ourrwcp - 1
316  IF (ourverbosity>2) THEN
317  WRITE (*,fmt='(A)') ' done'
318  END IF
319  IF (ourverbosity>0) THEN
320  WRITE (*,'(A)') 'summary:'
321  WRITE (*,'(A,I8)') ' overhead forward steps:', ournumfwd
322  WRITE (*,'(A,I8)') ' CP stores :', ournumstore
323  WRITE (*,'(A,I8)') ' rvNextAction calls :', ournuminv
324  END IF
325  rvnextaction%actionFlag = rvdone
326  ELSE
327  ourcstart = ourstepof(ourrwcp)
328  ourprevcend = ourcend
329  rvnextaction%actionFlag = rvrestore
330  END IF
331  ELSE IF ((ourcend-ourcstart)==1) THEN
332  ourcend = ourcend - 1
333  ourprevcend = ourcend
334  IF ((ourrwcp>=0) .AND. (ourstepof(ourrwcp)==ourcstart)) ourrwcp = ourrwcp - 1
335  IF (.NOT.ourfirstuturned) THEN
336  rvnextaction%actionFlag = rvfirstuturn
337  ourfirstuturned = .true.
338  ELSE
339  rvnextaction%actionFlag = rvuturn
340  END IF
341  ELSE IF (rwcptest) THEN
342  ourrwcp = ourrwcp + 1
343  IF (ourrwcp+1>ouracp) THEN
344  rvnextaction%actionFlag = rverror
345  rvnextaction%errorMsgRevolve='revolve::rvNextAction: insufficient allowed checkpoints'
346  RETURN
347  ELSE
348  ourstepof(ourrwcp) = ourcstart
349  ournumstore = ournumstore + 1
350  ourprevcend = ourcend
351  rvnextaction%actionFlag = rvstore
352  END IF
353  ELSE IF ((ourprevcend<ourcend) .AND. (ouracp==ourrwcp+1)) THEN
354  rvnextaction%actionFlag = rverror
355  rvnextaction%errorMsgRevolve='revolve::rvNextAction: insufficient allowed checkpoints'
356  ELSE
357  availcp = ouracp - ourrwcp
358  IF (availcp<1) THEN
359  rvnextaction%actionFlag = rverror
360  rvnextaction%errorMsgRevolve='revolve::rvNextAction: insufficient allowed checkpoints'
361  ELSE
362  reps = 0
363  range = 1
364  DO WHILE (range<ourcend-ourcstart)
365  reps = reps + 1
366  range = range*(reps+availcp)/reps
367  END DO
368  bino1 = range*reps/(availcp+reps)
369  IF (availcp>1) THEN
370  bino2 = bino1*availcp/(availcp+reps-1)
371  ELSE
372  bino2 = 1
373  END IF
374  IF (availcp==1) THEN
375  bino3 = 0
376  ELSE IF (availcp>2) THEN
377  bino3 = bino2*(availcp-1)/(availcp+reps-2)
378  ELSE
379  bino3 = 1
380  END IF
381  bino4 = bino2*(reps-1)/availcp
382  IF (availcp<3) THEN
383  bino5 = 0
384  ELSE IF (availcp>3) THEN
385  bino5 = bino3*(availcp-1)/reps
386  ELSE
387  bino5 = 1
388  END IF
389  IF (ourcend-ourcstart<=bino1+bino3) THEN
390  ourcstart = int(ourcstart + bino4)
391  ELSE IF (ourcend-ourcstart>=range-bino5) THEN
392  ourcstart = int(ourcstart + bino1)
393  ELSE
394  ourcstart = int(ourcend - bino2 - bino3)
395  END IF
396  IF (ourcstart==prevcstart) THEN
397  ourcstart = prevcstart + 1
398  END IF
399  IF (ourcstart==oursteps) THEN
400  ournumfwd = ournumfwd + ((ourcstart-1) - prevcstart)*ourbundle + ourtail
401  ELSE
402  ournumfwd = ournumfwd + (ourcstart - prevcstart)*ourbundle
403  END IF
404  rvnextaction%actionFlag = rvforward
405  END IF
406  END IF
407  rvnextaction%startIteration=prevcstart*ourbundle
408  IF (rvnextaction%actionFlag==rvfirstuturn) THEN
409  rvnextaction%iteration=(ourcstart)*ourbundle+ourtail
410  ELSE IF (rvnextaction%actionFlag==rvuturn) THEN
411  rvnextaction%iteration=(ourcstart+1)*ourbundle
412  ELSE
413  rvnextaction%iteration=(ourcstart)*ourbundle
414  END IF
415  IF (rvnextaction%actionFlag /= rverror) THEN
416  IF (ourverbosity>2) THEN
417  SELECT CASE( rvnextaction%actionFlag)
418  CASE (rvforward)
419  WRITE (*,fmt='(A,I8,A,I8,A)') ' run forward iterations [', &
420  rvnextaction%startIteration, ',', rvnextaction%iteration-1,']'
421  CASE (rvrestore)
422  WRITE (*,fmt='(A,I8)') ' restore input of iteration ',&
423  rvnextaction%iteration
424  CASE (rvfirstuturn)
425  WRITE (*,fmt='(A,I8,A,I8,A)') ' 1st uturn for iterations [',&
426  rvnextaction%startIteration, ',', rvnextaction%iteration-1,']'
427  CASE(rvuturn)
428  WRITE (*,fmt='(A,I8,A,I8,A)') ' uturn for iterations [',&
429  rvnextaction%startIteration, ',', rvnextaction%iteration-1,']'
430  END SELECT
431  END IF
432  IF ((ourverbosity>1) .AND. (rvnextaction%actionFlag == rvstore)) THEN
433  WRITE (*,fmt='(A,I8)') ' store input of iteration ',&
434  rvnextaction%iteration
435  END IF
436  END IF
437  rvnextaction%cpNum=ourrwcp
438  END FUNCTION rvnextaction
439 
440 !--------------------------------------------------------------------*
441  !> estimates the number of checkpoints required; equivalent to `adjust` in Alg. 799
442  !! @param steps is the number of iterations
443  !! @param bundle is optional; detaults to 1, if specified indicates the number of iterations bundled in one tape/adjoint sweep
444  !! @return the number of checkpoints such that the growth in spatial complexity is balanced with the growth in temporal complexity
445  !!
446  !! this method does not change the internal state and does not require \ref rvInit
447  FUNCTION rvguess(steps,bundle)
448  IMPLICIT NONE
449  INTEGER, INTENT(IN) :: steps, bundle
450  OPTIONAL :: bundle
451  INTEGER :: reps, s, checkpoints, b, tail, bSteps
452  INTEGER :: rvGuess
453  b=1
454  bsteps=steps
455  IF (present(bundle)) THEN
456  b=bundle
457  END IF
458  IF (steps<1) THEN
459  WRITE (*,fmt=*) 'revolve::rvGuess: error: steps < 1'
460  rvguess = -1
461  ELSE IF (b<1) THEN
462  WRITE (*,fmt=*) 'revolve::rvGuess: error: bundle < 1'
463  rvguess = -1
464  ELSE
465  IF (b .gt. 1) THEN
466  tail=modulo(bsteps,b)
467  bsteps=bsteps/b
468  IF (tail>0) THEN
469  bsteps=bsteps+1
470  END IF
471  END IF
472  IF (bsteps==1) THEN
473  rvguess=0
474  ELSE
475  checkpoints = 1
476  reps = 1
477  s = 0
478  DO WHILE (chkrange(checkpoints+s,reps+s)>bsteps)
479  s = s - 1
480  END DO
481  DO WHILE (chkrange(checkpoints+s,reps+s)<bsteps)
482  s = s + 1
483  END DO
484  checkpoints = checkpoints + s
485  reps = reps + s
486  s = -1
487  DO WHILE (chkrange(checkpoints,reps)>=bsteps)
488  IF (checkpoints>reps) THEN
489  checkpoints = checkpoints - 1
490  s = 0
491  ELSE
492  reps = reps - 1
493  s = 1
494  END IF
495  END DO
496  IF (s==0) THEN
497  checkpoints = checkpoints + 1
498  END IF
499  IF (s==1) reps = reps + 1
500  rvguess = checkpoints
501  END IF
502  END IF
503  END FUNCTION rvguess
504 
505 !--------------------------------------------------------------------*
506  !> computes the run time overhead factor; equivalent to `expense` in Alg. 799
507  !! @param steps is the number of iterations
508  !! @param checkpoints is the number of allowed checkpoints
509  !! @param bundle is optional; detaults to 1, if specified indicates the number of iterations bundled in one tape/adjoint sweep
510  !! @return the estimated runtime overhead factor (does not account for the time needed to write checkpoints)
511  !!
512  !! this method does not change the internal state and does not require \ref rvInit
513  FUNCTION rvfactor(steps,checkpoints,bundle)
514  IMPLICIT NONE
515  INTEGER, INTENT(IN) :: checkpoints, steps, bundle
516  OPTIONAL :: bundle
517  INTEGER :: b, f
518  DOUBLE PRECISION :: rvFactor
519  b=1
520  IF (present(bundle)) THEN
521  b=bundle
522  END IF
523  f=forwdcount(steps,checkpoints,b)
524  IF (f==-1) THEN
525  WRITE (*,fmt=*) 'revolve::rvFactor: error returned by revolve::forwdCount'
526  rvfactor=-1
527  ELSE
528  rvfactor = dble(f)/steps
529  END IF
530  END FUNCTION rvfactor
531 
532 !--------------------------------------------------------------------*
533  !> internal method not to be referenced by the user
534  FUNCTION chkrange(ss,tt)
535  IMPLICIT NONE
536  INTEGER :: ss, tt
537  DOUBLE PRECISION :: res
538  INTEGER :: i
539  INTEGER :: chkRange
540  res = 1.
541  IF (tt<0 .OR. ss<0) THEN
542  WRITE (*,fmt=*) 'revolve::chkRange: error: negative parameter '
543  chkrange = -1
544  ELSE
545  DO i = 1, tt
546  res = res*(ss+i)
547  res = res/i
548  IF (res>huge(chkrange)) EXIT
549  END DO
550  IF (res<huge(chkrange)) THEN
551  chkrange = int(res)
552  ELSE
553  chkrange = huge(chkrange)
554  WRITE (*,fmt=*) 'revolve::chkRange: warning: returning maximal integer ',&
555  chkrange
556  END IF
557  END IF
558  END FUNCTION chkrange
559 
560 !--------------------------------------------------------------------*
561 
562  !> internal method not to be referenced by the user;
563  !> predicts the number of recomputation-from-checkpoint forwards steps (overhead)
564  FUNCTION forwdcount(steps,checkpoints,bundle)
565  IMPLICIT NONE
566  INTEGER, INTENT(IN) :: checkpoints, steps, bundle
567  INTEGER :: range, reps,s,tail
568  INTEGER :: forwdCount
569  IF (checkpoints<0) THEN
570  WRITE (*,fmt=*) 'revolve::forwdCount: error: checkpoints < 0'
571  forwdcount = -1
572  ELSE IF (steps<1) THEN
573  WRITE (*,fmt=*) 'revolve::forwdCount: error: steps < 1'
574  forwdcount = -1
575  ELSE IF (bundle<1) THEN
576  WRITE (*,fmt=*) 'revolve::forwdCount: error: bundle < 1'
577  forwdcount = -1
578  ELSE
579  s=steps
580  IF (bundle .gt. 1) THEN
581  tail=modulo(s,bundle)
582  s=s/bundle
583  IF (tail>0) THEN
584  s=s+1
585  END IF
586  END IF
587  IF (s==1) THEN
588  forwdcount = 0
589  ELSE IF (checkpoints==0) THEN
590  WRITE (*,fmt=*) &
591  'revolve::forwdCount: error: given inputs require checkpoints>0'
592  forwdcount = -1
593  ELSE
594  reps = 0
595  range = 1
596  DO WHILE (range<s)
597  reps = reps + 1
598  range = range*(reps+checkpoints)/reps
599  END DO
600  forwdcount = (reps*s - range*reps/(checkpoints+1))*bundle
601  END IF
602  END IF
603  END FUNCTION forwdcount
604 
605 !--------------------------------------------------------------------*
606 
607 END MODULE revolve
integer, parameter, public rvfirstuturn
tape iteration(s); optionally leave to return later; and (upon return) do the adjoint(s) equivalent t...
Definition: revolve.f90:45
integer, parameter, public rvstore
store a checkpoint now equivalent to TAKESHOT in Alg. 799
Definition: revolve.f90:33
integer, parameter, public rverror
an error has occurred equivalent to the error enum value in Alg. 799; see also errorMsgRevolve in rvA...
Definition: revolve.f90:58
integer, parameter, public rvdone
we are done with adjoining the loop equivalent to the terminate enum value in Alg. 799
Definition: revolve.f90:53
integer, parameter, public rvforward
execute iteration(s) forward equivalent to ADVANCE in Alg. 799
Definition: revolve.f90:41
integer, parameter, public rvuturn
tape iteration(s) and do the adjoint(s) equivalent to YOUTURN in Alg. 799
Definition: revolve.f90:49
integer, dimension(:), allocatable ourstepof
vector of step numbers indexed by checkpoint; not to be set/referemced directly by the user ...
Definition: revolve.f90:159
integer ourtail
the number of iterations in the last bundle set by calling rvInit; not supposed to be set/used direct...
Definition: revolve.f90:116
the module containing the revolve implementation
Definition: revolve.f90:17
integer ourbundle
the number of iterations that may be bundled for a taping/adjoining sweep; set by calling rvInit; not...
Definition: revolve.f90:110
integer, parameter, public rvrestore
restore a checkpoint now equivalent to RESTORE in Alg. 799
Definition: revolve.f90:37