1 |
utke |
1.1 |
MODULE revolve |
2 |
|
|
IMPLICIT NONE |
3 |
|
|
|
4 |
|
|
PUBLIC :: rvInit, rvVerbose, rvNextAction, rvGuess, rvFactor, & |
5 |
|
|
rvStore, rvRestore, rvForward, rvFirstUTurn, rvUTurn, rvDone, rvError |
6 |
|
|
|
7 |
|
|
PRIVATE :: & |
8 |
|
|
ourSteps, ourACP, ourCStart, ourCEnd, ourVerbosity, & |
9 |
|
|
ourNumFwd , ourNumInv, ourNumStore, ourRWCP, ourPrevCEnd, ourFirstUTurned, & |
10 |
|
|
chkRange, forwdCount |
11 |
|
|
|
12 |
|
|
! possible actions |
13 |
|
|
INTEGER, PARAMETER :: rvStore =1 |
14 |
|
|
INTEGER, PARAMETER :: rvRestore =2 |
15 |
|
|
INTEGER, PARAMETER :: rvForward =3 |
16 |
|
|
INTEGER, PARAMETER :: rvFirstUTurn =4 |
17 |
|
|
INTEGER, PARAMETER :: rvUTurn =5 |
18 |
|
|
INTEGER, PARAMETER :: rvDone =6 |
19 |
|
|
INTEGER, PARAMETER :: rvError =7 |
20 |
|
|
|
21 |
|
|
TYPE rvAction |
22 |
|
|
INTEGER :: actionFlag = 0 |
23 |
|
|
INTEGER :: iteration = 0 |
24 |
|
|
INTEGER :: cpNum = 0 |
25 |
|
|
CHARACTER, dimension(80) :: errorMsg |
26 |
|
|
END TYPE rvAction |
27 |
|
|
|
28 |
|
|
INTEGER :: ourSteps = 0 ! number of steps |
29 |
|
|
INTEGER :: ourACP = 0 ! allowed number of checkpoints |
30 |
|
|
INTEGER :: ourCStart = 0 ! current subrange start |
31 |
|
|
INTEGER :: ourCEnd = 0 ! current subrange end |
32 |
|
|
INTEGER :: ourNumFwd = 0 ! count of forward steps |
33 |
|
|
INTEGER :: ourNumInv = 0 ! count of invocations of rvNextAction |
34 |
|
|
INTEGER :: ourNumStore = 0 ! number of stored checkpoints |
35 |
|
|
INTEGER :: ourRWCP = -1! checkpoint currently (re)stored (first checkpoint is 0) |
36 |
|
|
INTEGER :: ourPrevCEnd = 0 ! previous subrange end |
37 |
|
|
LOGICAL :: ourFirstUturned = .FALSE. ! have we first for the first time |
38 |
|
|
! vector of step numbers indexed by checkpoint |
39 |
|
|
INTEGER, DIMENSION(:), ALLOCATABLE :: ourStepOf |
40 |
|
|
|
41 |
|
|
! for debugging purposes: |
42 |
|
|
! 0 includes errors |
43 |
|
|
! 1 includes summary info |
44 |
|
|
! 2 includes iterations with checkpoints stored |
45 |
|
|
! 3 includes all action results |
46 |
|
|
INTEGER :: ourVerbosity = 0 |
47 |
|
|
|
48 |
|
|
CONTAINS |
49 |
|
|
|
50 |
|
|
!--------------------------------------------------------------------* |
51 |
|
|
|
52 |
|
|
FUNCTION rvInit(steps,checkpoints,errorMsg,anActionInstance) |
53 |
|
|
IMPLICIT NONE |
54 |
|
|
LOGICAL :: rvInit |
55 |
|
|
INTEGER, INTENT(IN) :: steps |
56 |
|
|
INTEGER, INTENT(IN) :: checkpoints |
57 |
|
|
CHARACTER ,dimension(:), INTENT(OUT) :: errorMsg |
58 |
|
|
type(rvAction), optional :: anActionInstance |
59 |
|
|
INTEGER :: predFwdCnt ! predicted forward count |
60 |
|
|
rvInit = .TRUE. |
61 |
|
|
errorMsg ='none' |
62 |
|
|
IF (present(anActionInstance)) THEN |
63 |
|
|
! same as default init above |
64 |
|
|
anActionInstance%actionFlag = 0 |
65 |
|
|
anActionInstance%iteration = 0 |
66 |
|
|
anActionInstance%cpNum = 0 |
67 |
|
|
END IF |
68 |
|
|
IF (steps<0 .OR. checkpoints<0) THEN |
69 |
|
|
rvInit=.FALSE. |
70 |
|
|
errorMsg = 'revolve::rvInit: negative steps or checkpoints' |
71 |
|
|
ELSE |
72 |
|
|
ourCStart = 0 |
73 |
|
|
ourSteps = steps |
74 |
|
|
ourCEnd = steps |
75 |
|
|
ourACP = checkpoints |
76 |
|
|
ourNumFwd = 0 |
77 |
|
|
ourNumInv = 0 |
78 |
|
|
ourNumStore = 0 |
79 |
|
|
ourRWCP = -1 |
80 |
|
|
ourPrevCEnd = 0 |
81 |
|
|
ourFirstUTurned = .FALSE. |
82 |
|
|
|
83 |
|
|
IF (ALLOCATED(ourStepOf)) THEN |
84 |
|
|
DEALLOCATE(ourStepOf) |
85 |
|
|
END IF |
86 |
|
|
IF(.NOT.ALLOCATED(ourStepOf)) THEN |
87 |
|
|
ALLOCATE(ourStepOf(0:ourACP)) |
88 |
|
|
END IF |
89 |
|
|
|
90 |
|
|
IF (ourVerbosity>0) THEN |
91 |
|
|
predFwdCnt = forwdCount(ourCEnd-ourCStart,ourACP) |
92 |
|
|
IF (predFwdCnt==-1) THEN |
93 |
|
|
errorMsg='error in forwdCount' |
94 |
|
|
RETURN |
95 |
|
|
ELSE |
96 |
|
|
WRITE (*,'(A)') 'prediction:' |
97 |
|
|
WRITE (*,'(A,I7)') ' needed forward steps: ', predFwdCnt |
98 |
|
|
WRITE (*,'(A,F8.4)') ' slowdown factor : ', dble(predFwdCnt)/(ourCEnd-ourCStart) |
99 |
|
|
END IF |
100 |
|
|
END IF |
101 |
|
|
END IF |
102 |
|
|
END FUNCTION rvInit |
103 |
|
|
|
104 |
|
|
!--------------------------------------------------------------------* |
105 |
|
|
|
106 |
|
|
SUBROUTINE rvVerbose(level) |
107 |
|
|
IMPLICIT NONE |
108 |
|
|
INTEGER, INTENT(IN) :: level |
109 |
|
|
ourVerbosity=level |
110 |
|
|
END SUBROUTINE rvVerbose |
111 |
|
|
|
112 |
|
|
!--------------------------------------------------------------------* |
113 |
|
|
|
114 |
|
|
FUNCTION rvNextAction() |
115 |
|
|
IMPLICIT NONE |
116 |
|
|
REAL :: bino1, bino2, bino3, bino4, bino5 |
117 |
|
|
INTEGER :: availCP ! available checkpoint slots |
118 |
|
|
INTEGER :: prevCStart ! previous subrange start |
119 |
|
|
INTEGER :: range ! |
120 |
|
|
INTEGER :: reps |
121 |
|
|
INTEGER :: i |
122 |
|
|
type(rvAction) :: rvNextAction |
123 |
|
|
IF (ourNumInv==0) THEN |
124 |
|
|
! first invocation |
125 |
|
|
DO i = 0, ourACP |
126 |
|
|
ourStepOf(i) = 0 |
127 |
|
|
END DO |
128 |
|
|
ourStepOf(0) = ourCStart - 1 |
129 |
|
|
END IF |
130 |
|
|
ourNumInv = ourNumInv + 1 |
131 |
|
|
IF ((ourCEnd-ourCStart)==0) THEN |
132 |
|
|
! nothing in current subrange |
133 |
|
|
IF ((ourRWCP==(-1)) .OR. (ourCStart==ourStepOf(0))) THEN |
134 |
|
|
! we are done |
135 |
|
|
ourRWCP = ourRWCP - 1 |
136 |
|
|
IF (ourVerbosity>0) THEN |
137 |
|
|
WRITE (*,'(A)') 'summary:' |
138 |
|
|
WRITE (*,'(A,I8)') ' forward steps:', ourNumFwd |
139 |
|
|
WRITE (*,'(A,I8)') ' CP stores :', ourNumStore |
140 |
|
|
WRITE (*,'(A,I8)') ' invocations :', ourNumInv |
141 |
|
|
END IF |
142 |
|
|
rvNextAction%actionFlag = rvDone |
143 |
|
|
ELSE |
144 |
|
|
ourCStart = ourStepOf(ourRWCP) |
145 |
|
|
ourPrevCEnd = ourCEnd |
146 |
|
|
rvNextAction%actionFlag = rvRestore |
147 |
|
|
END IF |
148 |
|
|
ELSE IF ((ourCEnd-ourCStart)==1) THEN |
149 |
|
|
ourCEnd = ourCEnd - 1 |
150 |
|
|
ourPrevCEnd = ourCEnd |
151 |
|
|
IF ((ourRWCP>=0) .AND. (ourStepOf(ourRWCP)==ourCStart)) ourRWCP = ourRWCP - 1 |
152 |
|
|
IF (.NOT.ourFirstUTurned) THEN |
153 |
|
|
rvNextAction%actionFlag = rvFirstUTurn |
154 |
|
|
ourFirstUTurned = .TRUE. |
155 |
|
|
ELSE |
156 |
|
|
rvNextAction%actionFlag = rvUTurn |
157 |
|
|
END IF |
158 |
|
|
ELSE IF ((ourRWCP==(-1)) .OR. (ourStepOf(ourRWCP)/=ourCStart)) THEN |
159 |
|
|
ourRWCP = ourRWCP + 1 |
160 |
|
|
IF (ourRWCP+1>ourACP) THEN |
161 |
|
|
rvNextAction%actionFlag = rvError |
162 |
|
|
rvNextAction%errorMsg='insufficient allowed checkpoints' |
163 |
|
|
RETURN |
164 |
|
|
ELSE |
165 |
|
|
ourStepOf(ourRWCP) = ourCStart |
166 |
|
|
ourNumStore = ourNumStore + 1 |
167 |
|
|
ourPrevCEnd = ourCEnd |
168 |
|
|
rvNextAction%actionFlag = rvStore |
169 |
|
|
END IF |
170 |
|
|
ELSE IF ((ourPrevCEnd<ourCEnd) .AND. (ourACP==ourRWCP+1)) THEN |
171 |
|
|
rvNextAction%actionFlag = rvError |
172 |
|
|
rvNextAction%errorMsg='insufficient allowed checkpoints' |
173 |
|
|
ELSE |
174 |
|
|
prevCStart = ourCStart |
175 |
|
|
availCP = ourACP - ourRWCP |
176 |
|
|
IF (availCP<1) THEN |
177 |
|
|
rvNextAction%actionFlag = rvError |
178 |
|
|
rvNextAction%errorMsg='insufficient allowed checkpoints' |
179 |
|
|
ELSE |
180 |
|
|
reps = 0 |
181 |
|
|
range = 1 |
182 |
|
|
DO WHILE (range<ourCEnd-ourCStart) |
183 |
|
|
reps = reps + 1 |
184 |
|
|
range = range*(reps+availCP)/reps |
185 |
|
|
END DO |
186 |
|
|
bino1 = range*reps/(availCP+reps) |
187 |
|
|
IF (availCP>1) THEN |
188 |
|
|
bino2 = bino1*availCP/(availCP+reps-1) |
189 |
|
|
ELSE |
190 |
|
|
bino2 = 1 |
191 |
|
|
END IF |
192 |
|
|
IF (availCP==1) THEN |
193 |
|
|
bino3 = 0 |
194 |
|
|
ELSE IF (availCP>2) THEN |
195 |
|
|
bino3 = bino2*(availCP-1)/(availCP+reps-2) |
196 |
|
|
ELSE |
197 |
|
|
bino3 = 1 |
198 |
|
|
END IF |
199 |
|
|
bino4 = bino2*(reps-1)/availCP |
200 |
|
|
IF (availCP<3) THEN |
201 |
|
|
bino5 = 0 |
202 |
|
|
ELSE IF (availCP>3) THEN |
203 |
|
|
bino5 = bino3*(availCP-1)/reps |
204 |
|
|
ELSE |
205 |
|
|
bino5 = 1 |
206 |
|
|
END IF |
207 |
|
|
IF (ourCEnd-ourCStart<=bino1+bino3) THEN |
208 |
|
|
ourCStart = ourCStart + bino4 |
209 |
|
|
ELSE IF (ourCEnd-ourCStart>=range-bino5) THEN |
210 |
|
|
ourCStart = ourCStart + bino1 |
211 |
|
|
ELSE |
212 |
|
|
ourCStart = ourCEnd - bino2 - bino3 |
213 |
|
|
END IF |
214 |
|
|
IF (ourCStart==prevCStart) THEN |
215 |
|
|
ourCStart = prevCStart + 1 |
216 |
|
|
END IF |
217 |
|
|
ourNumFwd = ourNumFwd + ourCStart - prevCStart |
218 |
|
|
rvNextAction%actionFlag = rvForward |
219 |
|
|
END IF |
220 |
|
|
END IF |
221 |
|
|
rvNextAction%iteration=ourCStart |
222 |
|
|
IF (rvNextAction%actionFlag /= rvError .AND. rvNextAction%actionFlag /= rvDone) THEN |
223 |
|
|
IF (ourVerbosity>2) THEN |
224 |
|
|
SELECT CASE( rvNextAction%actionFlag) |
225 |
|
|
CASE (rvForward) |
226 |
|
|
WRITE (*,FMT='(A)',ADVANCE='NO') ' forward to :' |
227 |
|
|
CASE (rvRestore) |
228 |
|
|
WRITE (*,FMT='(A)',ADVANCE='NO') ' restore at :' |
229 |
|
|
CASE (rvFirstUTurn) |
230 |
|
|
WRITE (*,FMT='(A)',ADVANCE='NO') ' 1st uturn at:' |
231 |
|
|
CASE(rvUTurn) |
232 |
|
|
WRITE (*,FMT='(A)',ADVANCE='NO') ' uturn at :' |
233 |
|
|
END SELECT |
234 |
|
|
END IF |
235 |
|
|
IF (ourVerbosity>1) THEN |
236 |
|
|
IF (rvNextAction%actionFlag == rvStore) THEN |
237 |
|
|
WRITE (*,FMT='(A)',ADVANCE='NO') ' store at :' |
238 |
|
|
END IF |
239 |
|
|
WRITE (*,'(I8)') rvNextAction%iteration |
240 |
|
|
END IF |
241 |
|
|
END IF |
242 |
|
|
rvNextAction%cpNum=ourRWCP |
243 |
|
|
END FUNCTION rvNextAction |
244 |
|
|
|
245 |
|
|
!--------------------------------------------------------------------* |
246 |
|
|
|
247 |
|
|
FUNCTION rvGuess(steps) |
248 |
|
|
IMPLICIT NONE |
249 |
|
|
INTEGER :: steps |
250 |
|
|
INTEGER :: reps, s, checkpoints |
251 |
|
|
INTEGER :: rvGuess |
252 |
|
|
checkpoints = 1 |
253 |
|
|
reps = 1 |
254 |
|
|
s = 0 |
255 |
|
|
DO WHILE (chkRange(checkpoints+s,reps+s)>steps) |
256 |
|
|
s = s - 1 |
257 |
|
|
END DO |
258 |
|
|
DO WHILE (chkRange(checkpoints+s,reps+s)<steps) |
259 |
|
|
s = s + 1 |
260 |
|
|
END DO |
261 |
|
|
checkpoints = checkpoints + s |
262 |
|
|
reps = reps + s |
263 |
|
|
s = -1 |
264 |
|
|
DO WHILE (chkRange(checkpoints,reps)>=steps) |
265 |
|
|
IF (checkpoints>reps) THEN |
266 |
|
|
checkpoints = checkpoints - 1 |
267 |
|
|
s = 0 |
268 |
|
|
ELSE |
269 |
|
|
reps = reps - 1 |
270 |
|
|
s = 1 |
271 |
|
|
END IF |
272 |
|
|
END DO |
273 |
|
|
IF (s==0) THEN |
274 |
|
|
checkpoints = checkpoints + 1 |
275 |
|
|
END IF |
276 |
|
|
IF (s==1) reps = reps + 1 |
277 |
|
|
rvGuess = checkpoints |
278 |
|
|
END FUNCTION rvGuess |
279 |
|
|
|
280 |
|
|
!--------------------------------------------------------------------* |
281 |
|
|
|
282 |
|
|
FUNCTION rvFactor(steps,checkpoints) |
283 |
|
|
IMPLICIT NONE |
284 |
|
|
INTEGER :: checkpoints, steps |
285 |
|
|
DOUBLE PRECISION :: rvFactor |
286 |
|
|
IF (checkpoints<1) THEN |
287 |
|
|
WRITE (*,fmt=*) 'error occurs in RVFACTOR: CHECKPOINTS < 1' |
288 |
|
|
rvFactor = -1 |
289 |
|
|
ELSE IF (checkpoints<1) THEN |
290 |
|
|
WRITE (*,fmt=*) 'error occurs in RVFACTOR: CHECKPOINTS < 1' |
291 |
|
|
rvFactor = -1 |
292 |
|
|
ELSE |
293 |
|
|
rvFactor = dble(forwdCount(steps,checkpoints)) |
294 |
|
|
IF (rvFactor/=-1) rvFactor = rvFactor/steps |
295 |
|
|
END IF |
296 |
|
|
END FUNCTION rvFactor |
297 |
|
|
|
298 |
|
|
!--------------------------------------------------------------------* |
299 |
|
|
|
300 |
|
|
FUNCTION chkRange(ss,tt) |
301 |
|
|
IMPLICIT NONE |
302 |
|
|
INTEGER :: ss, tt |
303 |
|
|
DOUBLE PRECISION :: res |
304 |
|
|
INTEGER :: i |
305 |
|
|
INTEGER :: chkRange |
306 |
|
|
res = 1. |
307 |
|
|
IF (tt<0 .OR. ss<0) THEN |
308 |
|
|
WRITE (*,fmt=*) 'error in MAXRANGE: negative parameter ' |
309 |
|
|
chkRange = -1 |
310 |
|
|
ELSE |
311 |
|
|
DO i = 1, tt |
312 |
|
|
res = res*(ss+i) |
313 |
|
|
res = res/i |
314 |
|
|
IF (res>=2.0D0**31) EXIT |
315 |
|
|
END DO |
316 |
|
|
IF (res<2.0D0**31-2) THEN |
317 |
|
|
chkRange = res |
318 |
|
|
ELSE |
319 |
|
|
chkRange = 2.0D0**31 - 3 |
320 |
|
|
WRITE (*,fmt=*) 'warning from MAXRANGE: returned maximal integer' |
321 |
|
|
WRITE (*,fmt=*) chkRange |
322 |
|
|
END IF |
323 |
|
|
END IF |
324 |
|
|
END FUNCTION chkRange |
325 |
|
|
|
326 |
|
|
!--------------------------------------------------------------------* |
327 |
|
|
|
328 |
|
|
FUNCTION forwdCount(steps,checkpoints) |
329 |
|
|
IMPLICIT NONE |
330 |
|
|
INTEGER :: checkpoints, steps |
331 |
|
|
INTEGER :: range, reps |
332 |
|
|
INTEGER :: forwdCount |
333 |
|
|
IF (checkpoints<1) THEN |
334 |
|
|
forwdCount = -1 |
335 |
|
|
ELSE |
336 |
|
|
reps = 0 |
337 |
|
|
range = 1 |
338 |
|
|
DO WHILE (range<steps) |
339 |
|
|
reps = reps + 1 |
340 |
|
|
range = range*(reps+checkpoints)/reps |
341 |
|
|
END DO |
342 |
|
|
forwdCount = reps*steps - range*reps/(checkpoints+1) |
343 |
|
|
END IF |
344 |
|
|
END FUNCTION forwdCount |
345 |
|
|
|
346 |
|
|
!--------------------------------------------------------------------* |
347 |
|
|
|
348 |
|
|
END MODULE revolve |