/[MITgcm]/MITgcm/pkg/grdchk/grdchk_main.F
ViewVC logotype

Annotation of /MITgcm/pkg/grdchk/grdchk_main.F

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


Revision 1.38 - (hide annotations) (download)
Tue Aug 21 14:00:04 2012 UTC (11 years, 8 months ago) by gforget
Branch: MAIN
Changes since 1.37: +18 -44 lines
- attempt to fix grdchk in the case of useSingleCpuIO.
- "if ( myProcId .EQ. grdchkwhichproc .AND. ierr .EQ. 0 )"
  statements were moved from grdchk_main.F and into
  grdchk_getadxx.F grdchk_getxx.F grdchk_setxx.F.
- a global sum is applied to record numbers icvrec/layer
  out of grdchk_loc so that they be passed to I/O routines.

1 gforget 1.38 C $Header: /u/gcmpack/MITgcm/pkg/grdchk/grdchk_main.F,v 1.37 2012/08/15 23:05:48 jmc Exp $
2 heimbach 1.11 C $Name: $
3 heimbach 1.2
4 jmc 1.31 #include "GRDCHK_OPTIONS.h"
5 jmc 1.36 #include "AD_CONFIG.h"
6 heimbach 1.2
7 heimbach 1.3 CBOI
8     C
9     C !TITLE: GRADIENT CHECK
10     C !AUTHORS: mitgcm developers ( support@mitgcm.org )
11     C !AFFILIATION: Massachussetts Institute of Technology
12     C !DATE:
13     C !INTRODUCTION: gradient check package
14     c \bv
15     c Compare the gradients calculated by the adjoint model with
16     c finite difference approximations.
17     c
18     C !CALLING SEQUENCE:
19     c
20     c the_model_main
21     c |
22     c |-- ctrl_unpack
23     c |-- adthe_main_loop - unperturbed cost function and
24     c |-- ctrl_pack adjoint gradient are computed here
25     c |
26     c |-- grdchk_main
27     c |
28     c |-- grdchk_init
29     c |-- do icomp=... - loop over control vector elements
30     c |
31     c |-- grdchk_loc - determine location of icomp on grid
32     c |
33     c |-- grdchk_getxx - get control vector component from file
34     c | perturb it and write back to file
35 jmc 1.31 c |-- grdchk_getadxx - get gradient component calculated
36 heimbach 1.3 c | via adjoint
37     c |-- the_main_loop - forward run and cost evaluation
38     c | with perturbed control vector element
39     c |-- calculate ratio of adj. vs. finite difference gradient
40     c |
41     c |-- grdchk_setxx - Reset control vector element
42     c |
43     c |-- grdchk_print - print results
44     c \ev
45     CEOI
46    
47     CBOP
48     C !ROUTINE: grdchk_main
49     C !INTERFACE:
50     subroutine grdchk_main( mythid )
51 heimbach 1.2
52 heimbach 1.3 C !DESCRIPTION: \bv
53 heimbach 1.2 c ==================================================================
54     c SUBROUTINE grdchk_main
55     c ==================================================================
56     c o Compare the gradients calculated by the adjoint model with
57     c finite difference approximations.
58     c started: Christian Eckert eckert@mit.edu 24-Feb-2000
59 heimbach 1.4 c continued&finished: heimbach@mit.edu: 13-Jun-2001
60     c changed: mlosch@ocean.mit.edu: 09-May-2002
61     c - added centered difference vs. 1-sided difference option
62     c - improved output format for readability
63     c - added control variable hFacC
64 heimbach 1.7 c heimbach@mit.edu 24-Feb-2003
65     c - added tangent linear gradient checks
66     c - fixes for multiproc. gradient checks
67     c - added more control variables
68 jmc 1.31 c
69 heimbach 1.2 c ==================================================================
70     c SUBROUTINE grdchk_main
71     c ==================================================================
72 heimbach 1.3 C \ev
73 heimbach 1.2
74 heimbach 1.3 C !USES:
75 heimbach 1.2 implicit none
76    
77     c == global variables ==
78     #include "SIZE.h"
79     #include "EEPARAMS.h"
80     #include "PARAMS.h"
81     #include "grdchk.h"
82     #include "cost.h"
83 heimbach 1.21 #include "ctrl.h"
84 heimbach 1.9 #ifdef ALLOW_TANGENTLINEAR_RUN
85     #include "g_cost.h"
86     #endif
87 heimbach 1.2
88 heimbach 1.3 C !INPUT/OUTPUT PARAMETERS:
89 heimbach 1.2 c == routine arguments ==
90 jmc 1.31 integer mythid
91 heimbach 1.2
92 heimbach 1.11 #ifdef ALLOW_GRDCHK
93 heimbach 1.3 C !LOCAL VARIABLES:
94 heimbach 1.2 c == local variables ==
95     integer myiter
96 jmc 1.31 _RL mytime
97 heimbach 1.2 integer bi, itlo, ithi
98     integer bj, jtlo, jthi
99     integer i, imin, imax
100     integer j, jmin, jmax
101     integer k
102    
103     integer icomp
104     integer ichknum
105     integer icvrec
106     integer jtile
107     integer itile
108     integer layer
109 heimbach 1.8 integer obcspos
110 heimbach 1.2 integer itilepos
111     integer jtilepos
112 heimbach 1.19 integer icglo
113 heimbach 1.2 integer itest
114     integer ierr
115     integer ierr_grdchk
116     _RL gfd
117     _RL fcref
118 heimbach 1.4 _RL fcpertplus, fcpertminus
119 heimbach 1.6 _RL ratio_ad
120     _RL ratio_ftl
121 heimbach 1.2 _RL xxmemo_ref
122     _RL xxmemo_pert
123     _RL adxxmemo
124 heimbach 1.6 _RL ftlxxmemo
125     _RL localEps
126     _RL grdchk_epsfac
127    
128 heimbach 1.7 _RL tmpplot1(1-olx:snx+olx,1-oly:sny+oly,nr,nsx,nsy)
129     _RL tmpplot2(1-olx:snx+olx,1-oly:sny+oly,nr,nsx,nsy)
130     _RL tmpplot3(1-olx:snx+olx,1-oly:sny+oly,nr,nsx,nsy)
131    
132 heimbach 1.12 CHARACTER*(MAX_LEN_MBUF) msgBuf
133    
134 heimbach 1.2 c == end of interface ==
135 heimbach 1.3 CEOP
136 heimbach 1.2
137     c-- Set the loop ranges.
138     jtlo = mybylo(mythid)
139     jthi = mybyhi(mythid)
140     itlo = mybxlo(mythid)
141     ithi = mybxhi(mythid)
142     jmin = 1
143     jmax = sny
144     imin = 1
145     imax = snx
146    
147 heimbach 1.16 print *, 'ph-check entering grdchk_main '
148    
149 heimbach 1.2 c-- initialise variables
150     call grdchk_init( mythid )
151    
152 jmc 1.29 c-- Compute the adjoint model gradients.
153 heimbach 1.2 c-- Compute the unperturbed cost function.
154 heimbach 1.7 cph Gradient via adjoint has already been computed,
155     cph and so has unperturbed cost function,
156     cph assuming all xx_ fields are initialised to zero.
157 heimbach 1.2
158 heimbach 1.28 ierr = 0
159 heimbach 1.9 ierr_grdchk = 0
160 heimbach 1.27 adxxmemo = 0.
161     ftlxxmemo = 0.
162 heimbach 1.21 #ifdef ALLOW_ADMTLM
163     fcref = objf_state_final(idep,jdep,1,1,1)
164     #else
165 heimbach 1.2 fcref = fc
166 heimbach 1.21 #endif
167 heimbach 1.9
168     print *, 'ph-check fcref = ', fcref
169 heimbach 1.2
170     do bj = jtlo, jthi
171     do bi = itlo, ithi
172     do k = 1, nr
173     do j = jmin, jmax
174     do i = imin, imax
175     tmpplot1(i,j,k,bi,bj) = 0. _d 0
176     tmpplot2(i,j,k,bi,bj) = 0. _d 0
177 heimbach 1.6 tmpplot3(i,j,k,bi,bj) = 0. _d 0
178 heimbach 1.2 end do
179     end do
180     end do
181     end do
182     end do
183    
184 heimbach 1.4 if ( useCentralDiff ) then
185     grdchk_epsfac = 2. _d 0
186     else
187     grdchk_epsfac = 1. _d 0
188     end if
189    
190 heimbach 1.23 WRITE(standardmessageunit,'(A)')
191     & 'grad-res -------------------------------'
192     WRITE(standardmessageunit,'(2a)')
193 heimbach 1.19 & ' grad-res proc # i j k bi bj iobc',
194 heimbach 1.18 & ' fc ref fc + eps fc - eps'
195 heimbach 1.7 #ifdef ALLOW_TANGENTLINEAR_RUN
196 heimbach 1.23 WRITE(standardmessageunit,'(2a)')
197 heimbach 1.19 & ' grad-res proc # i j k bi bj iobc',
198 heimbach 1.18 & ' tlm grad fd grad 1 - fd/tlm'
199 heimbach 1.7 #else
200 heimbach 1.23 WRITE(standardmessageunit,'(2a)')
201 heimbach 1.19 & ' grad-res proc # i j k bi bj iobc',
202 heimbach 1.18 & ' adj grad fd grad 1 - fd/adj'
203 heimbach 1.7 #endif
204    
205 heimbach 1.2 c-- Compute the finite difference approximations.
206     c-- Cycle through all processes doing NINT(nend-nbeg+1)/nstep
207     c-- gradient checks.
208 heimbach 1.14
209 jmc 1.31 if ( nbeg .EQ. 0 )
210 heimbach 1.17 & call grdchk_get_position( mythid )
211 heimbach 1.2
212 heimbach 1.7 do icomp = nbeg, nend, nstep
213 heimbach 1.2
214 heimbach 1.7 ichknum = (icomp - nbeg)/nstep + 1
215 jmc 1.32 adxxmemo = 0.
216 heimbach 1.2
217 heimbach 1.19 cph(
218 jmc 1.31 cph-print print *, 'ph-grd _main: nbeg, icomp, ichknum ',
219 heimbach 1.19 cph-print & nbeg, icomp, ichknum
220     cph)
221 heimbach 1.7 if (ichknum .le. maxgrdchecks ) then
222 heimbach 1.2
223 heimbach 1.7 c-- Determine the location of icomp on the grid.
224     if ( myProcId .EQ. grdchkwhichproc ) then
225 jmc 1.31 call grdchk_loc( icomp, ichknum,
226 heimbach 1.8 & icvrec, itile, jtile, layer, obcspos,
227 heimbach 1.19 & itilepos, jtilepos, icglo, itest, ierr,
228 heimbach 1.7 & mythid )
229 heimbach 1.18 cph(
230 heimbach 1.19 cph-print print *, 'ph-grd ----- back from loc -----',
231     cph-print & icvrec, itilepos, jtilepos, layer, obcspos
232 heimbach 1.18 cph)
233 jmc 1.34 else
234 jmc 1.35 icvrec = 0
235 jmc 1.34 itile = 0
236     jtile = 0
237     layer = 0
238 jmc 1.35 obcspos = 0
239 jmc 1.34 itilepos = 0
240     jtilepos = 0
241 jmc 1.35 icglo = 0
242     itest = 0
243 heimbach 1.7 endif
244 jmc 1.31
245 gforget 1.38 c make sure that all procs have correct file records, so that useSingleCpuIO works
246     CALL GLOBAL_SUM_INT( icvrec , myThid )
247     CALL GLOBAL_SUM_INT( layer , myThid )
248    
249 heimbach 1.6 c******************************************************
250     c-- (A): get gradient component calculated via adjoint
251     c******************************************************
252 heimbach 1.7
253     c-- get gradient component calculated via adjoint
254     call grdchk_getadxx( icvrec,
255     & itile, jtile, layer,
256     & itilepos, jtilepos,
257 gforget 1.38 & adxxmemo, ierr, mythid )
258 jmc 1.32 C-- Add a global-sum call so that all proc will get the adjoint gradient
259     _GLOBAL_SUM_RL( adxxmemo, myThid )
260 heimbach 1.4
261 heimbach 1.6 #ifdef ALLOW_TANGENTLINEAR_RUN
262     c******************************************************
263     c-- (B): Get gradient component g_fc from tangent linear run:
264     c******************************************************
265     c--
266     c-- 1. perturb control vector component: xx(i)=1.
267    
268 heimbach 1.7 localEps = 1. _d 0
269     call grdchk_getxx( icvrec, TANGENT_SIMULATION,
270     & itile, jtile, layer,
271     & itilepos, jtilepos,
272     & xxmemo_ref, xxmemo_pert, localEps,
273 gforget 1.38 & ierr, mythid )
274 heimbach 1.6
275     c--
276     c-- 2. perform tangent linear run
277 heimbach 1.7 mytime = starttime
278     myiter = niter0
279 heimbach 1.21 #ifdef ALLOW_ADMTLM
280     do k=1,4*Nr+1
281     do j=1,sny
282     do i=1,snx
283     g_objf_state_final(i,j,1,1,k) = 0.
284     enddo
285     enddo
286     enddo
287     #else
288 heimbach 1.7 g_fc = 0.
289 heimbach 1.21 #endif
290    
291 heimbach 1.7 call g_the_main_loop( mytime, myiter, mythid )
292 heimbach 1.21 #ifdef ALLOW_ADMTLM
293     ftlxxmemo = g_objf_state_final(idep,jdep,1,1,1)
294     #else
295 heimbach 1.7 ftlxxmemo = g_fc
296 heimbach 1.21 #endif
297    
298 heimbach 1.6 c--
299     c-- 3. reset control vector
300 heimbach 1.7 call grdchk_setxx( icvrec, TANGENT_SIMULATION,
301     & itile, jtile, layer,
302     & itilepos, jtilepos,
303 gforget 1.38 & xxmemo_ref, ierr, mythid )
304 heimbach 1.7
305     #endif /* ALLOW_TANGENTLINEAR_RUN */
306    
307 heimbach 1.6
308     c******************************************************
309     c-- (C): Get gradient via finite difference perturbation
310     c******************************************************
311    
312 heimbach 1.2 c-- get control vector component from file
313 heimbach 1.7 c-- perturb it and write back to file
314 heimbach 1.6 c-- positive perturbation
315 heimbach 1.7 localEps = abs(grdchk_eps)
316 gforget 1.38 call grdchk_getxx( icvrec, FORWARD_SIMULATION,
317 heimbach 1.7 & itile, jtile, layer,
318     & itilepos, jtilepos,
319     & xxmemo_ref, xxmemo_pert, localEps,
320 gforget 1.38 & ierr, mythid )
321 jmc 1.31
322 heimbach 1.4 c-- forward run with perturbed control vector
323 heimbach 1.7 mytime = starttime
324     myiter = niter0
325     call the_main_loop( mytime, myiter, mythid )
326 heimbach 1.21 #ifdef ALLOW_ADMTLM
327     fcpertplus = objf_state_final(idep,jdep,1,1,1)
328     #else
329 heimbach 1.7 fcpertplus = fc
330 heimbach 1.21 #endif
331 jmc 1.37 print *, 'ph-check fcpertplus = ', fcpertplus
332 jmc 1.31
333 heimbach 1.4 c-- Reset control vector.
334 gforget 1.38 call grdchk_setxx( icvrec, FORWARD_SIMULATION,
335 heimbach 1.7 & itile, jtile, layer,
336     & itilepos, jtilepos,
337 gforget 1.38 & xxmemo_ref, ierr, mythid )
338 heimbach 1.2
339 heimbach 1.7 fcpertminus = fcref
340 heimbach 1.13 print *, 'ph-check fcpertminus = ', fcpertminus
341 heimbach 1.4
342 heimbach 1.7 if ( useCentralDiff ) then
343 heimbach 1.4
344 heimbach 1.6 c-- get control vector component from file
345 heimbach 1.7 c-- perturb it and write back to file
346 heimbach 1.4 c-- repeat the proceedure for a negative perturbation
347 gforget 1.38 localEps = - abs(grdchk_eps)
348     call grdchk_getxx( icvrec, FORWARD_SIMULATION,
349 heimbach 1.7 & itile, jtile, layer,
350     & itilepos, jtilepos,
351     & xxmemo_ref, xxmemo_pert, localEps,
352 gforget 1.38 & ierr, mythid )
353 jmc 1.31
354 heimbach 1.2 c-- forward run with perturbed control vector
355 heimbach 1.7 mytime = starttime
356     myiter = niter0
357     call the_main_loop( mytime, myiter, mythid )
358 heimbach 1.21 #ifdef ALLOW_ADMTLM
359     fcpertminus = objf_state_final(idep,jdep,1,1,1)
360     #else
361 heimbach 1.7 fcpertminus = fc
362 heimbach 1.21 #endif
363 jmc 1.31
364 heimbach 1.4 c-- Reset control vector.
365 gforget 1.38 call grdchk_setxx( icvrec, FORWARD_SIMULATION,
366 heimbach 1.7 & itile, jtile, layer,
367     & itilepos, jtilepos,
368 gforget 1.38 & xxmemo_ref, ierr, mythid )
369 heimbach 1.7
370     c-- end of if useCentralDiff ...
371     end if
372 heimbach 1.4
373 heimbach 1.6 c******************************************************
374     c-- (D): calculate relative differences between gradients
375     c******************************************************
376    
377 jmc 1.33 if ( grdchk_eps .eq. 0. ) then
378     gfd = (fcpertplus-fcpertminus)
379     else
380     gfd = (fcpertplus-fcpertminus)
381     & /(grdchk_epsfac*grdchk_eps)
382     endif
383 heimbach 1.2
384 jmc 1.33 if ( adxxmemo .eq. 0. ) then
385     ratio_ad = abs( adxxmemo - gfd )
386     else
387     ratio_ad = 1. - gfd/adxxmemo
388     endif
389 jmc 1.31
390 jmc 1.33 if ( ftlxxmemo .eq. 0. ) then
391     ratio_ftl = abs( ftlxxmemo - gfd )
392     else
393     ratio_ftl = 1. - gfd/ftlxxmemo
394     endif
395 heimbach 1.7
396 jmc 1.33 if ( myProcId .EQ. grdchkwhichproc .AND.
397     & ierr .EQ. 0 ) then
398 heimbach 1.7 tmpplot1(itilepos,jtilepos,layer,itile,jtile)
399     & = gfd
400     tmpplot2(itilepos,jtilepos,layer,itile,jtile)
401     & = ratio_ad
402     tmpplot3(itilepos,jtilepos,layer,itile,jtile)
403     & = ratio_ftl
404 jmc 1.34 endif
405 heimbach 1.7
406 jmc 1.34 if ( ierr .EQ. 0 ) then
407 heimbach 1.7 fcrmem ( ichknum ) = fcref
408     fcppmem ( ichknum ) = fcpertplus
409     fcpmmem ( ichknum ) = fcpertminus
410     xxmemref ( ichknum ) = xxmemo_ref
411     xxmempert ( ichknum ) = xxmemo_pert
412     gfdmem ( ichknum ) = gfd
413     adxxmem ( ichknum ) = adxxmemo
414     ftlxxmem ( ichknum ) = ftlxxmemo
415     ratioadmem ( ichknum ) = ratio_ad
416     ratioftlmem ( ichknum ) = ratio_ftl
417    
418     irecmem ( ichknum ) = icvrec
419     bimem ( ichknum ) = itile
420     bjmem ( ichknum ) = jtile
421     ilocmem ( ichknum ) = itilepos
422     jlocmem ( ichknum ) = jtilepos
423     klocmem ( ichknum ) = layer
424 heimbach 1.8 iobcsmem ( ichknum ) = obcspos
425 heimbach 1.7 icompmem ( ichknum ) = icomp
426     ichkmem ( ichknum ) = ichknum
427     itestmem ( ichknum ) = itest
428     ierrmem ( ichknum ) = ierr
429 heimbach 1.19 icglomem ( ichknum ) = icglo
430 jmc 1.34 endif
431    
432     if ( myProcId .EQ. grdchkwhichproc .AND.
433     & ierr .EQ. 0 ) then
434 heimbach 1.19
435 heimbach 1.23 WRITE(standardmessageunit,'(A)')
436     & 'grad-res -------------------------------'
437 jmc 1.32 WRITE(standardmessageunit,'(A,8I5,1x,1P3E19.11)')
438 heimbach 1.23 & ' grad-res ',myprocid,ichknum,itilepos,jtilepos,
439 heimbach 1.19 & layer,itile,jtile,obcspos,
440 heimbach 1.7 & fcref, fcpertplus, fcpertminus
441     #ifdef ALLOW_TANGENTLINEAR_RUN
442 jmc 1.32 WRITE(standardmessageunit,'(A,8I5,1x,1P3E19.11)')
443 heimbach 1.23 & ' grad-res ',myprocid,ichknum,ichkmem(ichknum),
444 heimbach 1.19 & icompmem(ichknum),itestmem(ichknum),
445     & bimem(ichknum),bjmem(ichknum),iobcsmem(ichknum),
446 heimbach 1.7 & ftlxxmemo, gfd, ratio_ftl
447     #else
448 jmc 1.32 WRITE(standardmessageunit,'(A,8I5,1x,1P3E19.11)')
449 heimbach 1.23 & ' grad-res ',myprocid,ichknum,ichkmem(ichknum),
450 heimbach 1.19 & icompmem(ichknum),itestmem(ichknum),
451     & bimem(ichknum),bjmem(ichknum),obcspos,
452 heimbach 1.7 & adxxmemo, gfd, ratio_ad
453 jmc 1.32 #endif
454     endif
455     #ifdef ALLOW_TANGENTLINEAR_RUN
456 jmc 1.37 WRITE(msgBuf,'(A30,1PE22.14)')
457     & ' TLM ref_cost_function =', fcref
458     CALL PRINT_MESSAGE( msgBuf, standardMessageUnit,
459     & SQUEEZE_RIGHT, myThid )
460     WRITE(msgBuf,'(A30,1PE22.14)')
461     & ' TLM tangent-lin_grad =', ftlxxmemo
462     CALL PRINT_MESSAGE( msgBuf, standardMessageUnit,
463     & SQUEEZE_RIGHT, myThid )
464     WRITE(msgBuf,'(A30,1PE22.14)')
465     & ' TLM finite-diff_grad =', gfd
466     CALL PRINT_MESSAGE( msgBuf, standardMessageUnit,
467     & SQUEEZE_RIGHT, myThid )
468 jmc 1.32 #else
469 jmc 1.33 WRITE(msgBuf,'(A30,1PE22.14)')
470     & ' ADM ref_cost_function =', fcref
471     CALL PRINT_MESSAGE( msgBuf, standardMessageUnit,
472     & SQUEEZE_RIGHT, myThid )
473     WRITE(msgBuf,'(A30,1PE22.14)')
474     & ' ADM adjoint_gradient =', adxxmemo
475     CALL PRINT_MESSAGE( msgBuf, standardMessageUnit,
476     & SQUEEZE_RIGHT, myThid )
477     WRITE(msgBuf,'(A30,1PE22.14)')
478     & ' ADM finite-diff_grad =', gfd
479     CALL PRINT_MESSAGE( msgBuf, standardMessageUnit,
480     & SQUEEZE_RIGHT, myThid )
481 heimbach 1.7 #endif
482    
483     print *, 'ph-grd ierr ---------------------------'
484     print *, 'ph-grd ierr = ', ierr, ', icomp = ', icomp,
485     & ', ichknum = ', ichknum
486    
487     c-- else of if ( ichknum ...
488     else
489     ierr_grdchk = -1
490    
491 jmc 1.31 c-- end of if ( ichknum ...
492 heimbach 1.2 endif
493    
494 jmc 1.31 c-- end of do icomp = ...
495 heimbach 1.7 enddo
496 heimbach 1.2
497 gforget 1.38 if (myProcId .EQ. grdchkwhichproc .AND. .NOT.useSingleCpuIO) then
498 jmc 1.31 CALL WRITE_REC_XYZ_RL(
499 heimbach 1.7 & 'grd_findiff' , tmpplot1, 1, 0, myThid)
500 jmc 1.31 CALL WRITE_REC_XYZ_RL(
501 heimbach 1.7 & 'grd_ratio_ad' , tmpplot2, 1, 0, myThid)
502 jmc 1.31 CALL WRITE_REC_XYZ_RL(
503 heimbach 1.7 & 'grd_ratio_ftl' , tmpplot3, 1, 0, myThid)
504     endif
505 heimbach 1.2
506 heimbach 1.7 c-- Everyone has to wait for the component to be reset.
507 jmc 1.37 c _BARRIER
508 heimbach 1.2
509     c-- Print the results of the gradient check.
510     call grdchk_print( ichknum, ierr_grdchk, mythid )
511    
512 heimbach 1.11 #endif /* ALLOW_GRDCHK */
513 heimbach 1.2
514 jmc 1.31 return
515 heimbach 1.2 end

  ViewVC Help
Powered by ViewVC 1.1.22