source: trunk/libIGCM/libIGCM_config/libIGCM_config.ksh @ 545

Last change on this file since 545 was 545, checked in by sdipsl, 12 years ago
  • clean_month.job adapted to R_BUFR
  • R_IN points to CCCWORKDIR /ccc/work/cont003/dsm/p86ipsl/IGCM
  • bugfixes, simplification, refactoring, cosmetics
  • Property licence set to
    The following licence information concerns ONLY the libIGCM tools
    ==================================================================

    Copyright © Centre National de la Recherche Scientifique CNRS
    Commissariat à l'Énergie Atomique CEA

    libIGCM : Library for Portable Models Computation of IGCM Group.

    IGCM Group is the french IPSL Global Climate Model Group.

    This library is a set of shell scripts and functions whose purpose is
    the management of the initialization, the launch, the transfer of
    output files, the post-processing and the monitoring of datas produce
    by any numerical program on any plateforme.

    This software is governed by the CeCILL license under French law and
    abiding by the rules of distribution of free software. You can use,
    modify and/ or redistribute the software under the terms of the CeCILL
    license as circulated by CEA, CNRS and INRIA at the following URL
    "http://www.cecill.info".

    As a counterpart to the access to the source code and rights to copy,
    modify and redistribute granted by the license, users are provided only
    with a limited warranty and the software's author, the holder of the
    economic rights, and the successive licensors have only limited
    liability.

    In this respect, the user's attention is drawn to the risks associated
    with loading, using, modifying and/or developing or reproducing the
    software by the user in light of its specific status of free software,
    that may mean that it is complicated to manipulate, and that also
    therefore means that it is reserved for developers and experienced
    professionals having in-depth computer knowledge. Users are therefore
    encouraged to load and test the software's suitability as regards their
    requirements in conditions enabling the security of their systems and/or
    data to be ensured and, more generally, to use and operate it in the
    same conditions as regards security.

    The fact that you are presently reading this means that you have had
    knowledge of the CeCILL license and that you accept its terms.
  • Property svn:keywords set to Revision Author Date
File size: 35.8 KB
Line 
1#!/bin/ksh
2
3#**************************************************************
4# Author: Sebastien Denvil, Martial Mancip
5# Contact: Sebastien.Denvil__at__ipsl.jussieu.fr Martial.Mancip__at__ipsl.jussieu.fr
6# $Revision::                                          $ Revision of last commit
7# $Author::                                            $ Author of last commit
8# $Date::                                              $ Date of last commit
9# IPSL (2006)
10#  This software is governed by the CeCILL licence see libIGCM/libIGCM_CeCILL.LIC
11#
12#**************************************************************
13
14#===================================
15function IGCM_config_Initialize
16{
17  IGCM_debug_PushStack "IGCM_config_Initialize"
18
19  # Debug Print :
20  echo
21  IGCM_debug_Print 1 "IGCM_config_Initialize"
22
23  if [ ! -r ${SUBMIT_DIR}/run.card ]; then 
24    #================================================#
25    #         The file run.card doesn't exist        #
26    #================================================#
27    FirstInitialize=true
28    #copy initial run.card
29    IGCM_sys_Cp ${SUBMIT_DIR}/run.card.init ${SUBMIT_DIR}/run.card
30    IGCM_debug_Print 2 "run.card copied from run.card.init"
31  else
32    FirstInitialize=false
33    IGCM_debug_Print 2 "run.card exists"
34  fi
35
36  # Test modipsl tree existence.
37  IGCM_sys_TestDir ${MODIPSL}
38  [ $? != 0 ] && IGCM_debug_Exit "IGCM_sys_TestDir"
39  IGCM_sys_TestDir ${libIGCM}
40  [ $? != 0 ] && IGCM_debug_Exit "IGCM_sys_TestDir"
41  IGCM_sys_TestDir ${R_EXE}
42  [ $? != 0 ] && IGCM_debug_Exit "IGCM_sys_TestDir"
43  IGCM_sys_TestDir ${SUBMIT_DIR}
44  [ $? != 0 ] && IGCM_debug_Exit "IGCM_sys_TestDir"
45
46  if ( $DEBUG_debug ) ; then
47    echo "Keep trace of inital SUBMIT_DIR : "
48    ls -lta ${SUBMIT_DIR}
49  fi
50
51  #==================================
52
53  typeset option auxprint CompatibilityTag
54  # Read libIGCM compatibility version in config.card
55  IGCM_card_DefineVariableFromOption ${SUBMIT_DIR}/config.card Compatibility libIGCM
56  eval CompatibilityTag=${config_Compatibility_libIGCM} > /dev/null 2>&1       
57
58  if [ ! "${CompatibilityTag}" = "${libIGCM_CurrentTag}" ] ; then
59    IGCM_debug_Exit "config.card is not compatible with libIGCM version ${libIGCM_CurrentTag} see libIGCM FAQ http://wiki.ipsl.jussieu.fr/wiki_ipsl/IGCMG/libIGCM/DocUtilisateur/FAQ ."
60  fi
61
62  #==================================
63  IGCM_card_DefineArrayFromSection ${SUBMIT_DIR}/config.card UserChoices
64
65  for option in ${config_UserChoices[*]} ; do
66    IGCM_card_DefineVariableFromOption ${SUBMIT_DIR}/config.card UserChoices ${option}
67  done
68  echo
69  IGCM_debug_Print 1 "DefineArrayFromOption  : config_UserChoices"
70  # Name Space of this experience
71  if [ X${config_UserChoices_SpaceName} != X ] ; then
72    IGCM_debug_PrintVariables 3 config_UserChoices_SpaceName
73  fi
74  # Expericence class of the run
75  if [ X${config_UserChoices_ExperimentName} != X ] ; then
76    IGCM_debug_PrintVariables 3 config_UserChoices_ExperimentName
77  fi
78  IGCM_debug_PrintVariables 3 config_UserChoices_JobName
79  if [ 3 -le ${Verbosity} ] ; then
80    echo "--------------Debug3-->" "config_UserChoices_LongName="
81    echo "--------------Debug3-->" \"${config_UserChoices_LongName}\"
82  fi
83  IGCM_debug_PrintVariables 3 config_UserChoices_TagName
84  IGCM_debug_PrintVariables 3 config_UserChoices_CalendarType
85  IGCM_debug_PrintVariables 3 config_UserChoices_DateBegin
86  IGCM_debug_PrintVariables 3 config_UserChoices_DateEnd
87  IGCM_debug_PrintVariables 3 config_UserChoices_PeriodLength
88
89  #==================================
90
91  IGCM_card_DefineArrayFromSection ${SUBMIT_DIR}/config.card ListOfComponents
92  for comp in ${config_ListOfComponents[*]} ; do
93    IGCM_card_DefineArrayFromOption ${SUBMIT_DIR}/config.card ListOfComponents ${comp}
94  done
95
96  echo
97  IGCM_debug_Print 1 "DefineArrayFromSection : ListOfComponents"
98  IGCM_debug_Print 3 ${config_ListOfComponents[*]}
99
100  NbComponents=${#config_ListOfComponents[*]}
101
102  #==================================
103  # Define principal executable
104  IGCM_card_DefineArrayFromSection   ${SUBMIT_DIR}/config.card Executable
105  IGCM_card_DefineVariableFromOption ${SUBMIT_DIR}/config.card Executable Name
106 
107  #==================================
108  # Define Outputs Name
109  IGCM_debug_Print 2 "Define Script_Output_Prefix and Exe_Output"
110  eval Script_Output_Prefix=${config_UserChoices_Script_Output_Prefix:='Script_Output'}
111  IGCM_debug_Print 3 "Script_Output_Prefix = ${Script_Output_Prefix}"
112  eval Exe_Output=out_${config_Executable_Name}
113  IGCM_debug_Print 3 "Exe_Output           = ${Exe_Output}"
114
115  #==================================
116
117  #===================================================================#
118  # Prepare variables available for ${COMP}.card and ${COMP}.driver   #
119  #             But available to any son functions                    #
120  #===================================================================#
121
122  # Convert yyyy-mm-dd date to gregorian yyyymmdd
123  DateBegin=$( IGCM_date_ConvertFormatToGregorian ${config_UserChoices_DateBegin} )
124  DateEnd=$( IGCM_date_ConvertFormatToGregorian ${config_UserChoices_DateEnd} )
125
126  # Period Length In Days between DateBegin and DateEnd
127  (( ExperienceLengthInDays=$( IGCM_date_DaysBetweenGregorianDate ${DateEnd} ${DateBegin} )  + 1 ))
128  if [ ${ExperienceLengthInDays} -lt 0 ] ; then
129    IGCM_debug_Print 1 "Problem with dates in config.card : ${DateEnd} < ${DateBegin} ! You must check that."
130    IGCM_debug_Exit "IGCM_config_Initialize" " Wrong Dates."
131    IGCM_debug_Verif_Exit
132  fi
133
134  # Day and Year of Initial State (Given in julian format)
135  InitDay=$(( $( IGCM_date_ConvertGregorianDateToJulian $DateBegin ) % 1000 ))
136  InitYear=$(( $( IGCM_date_ConvertGregorianDateToJulian $DateBegin ) / 1000 ))
137
138  #==================================
139  # Restarts : Gerneral rule or local for each component ?
140  IGCM_card_DefineArrayFromSection ${SUBMIT_DIR}/config.card Restarts
141
142  echo
143  IGCM_debug_Print 1 "DefineArrayFromOption : config_Restarts"
144
145  for option in ${config_Restarts[*]} ; do
146    IGCM_card_DefineVariableFromOption ${SUBMIT_DIR}/config.card Restarts ${option}
147    eval auxprint=\${config_Restarts_${option}}
148    IGCM_debug_Print 3 "${option} : ${auxprint}"
149  done
150
151  #================================================================#
152  #                  Test and Prepare directories                  #
153  #================================================================#
154
155  # ==> 4 kinds of input files :
156  #     1) R_INIT  : Initial State Files   (Etat0, carteveg)
157  #     2) R_BC    : Boundary Conditions   (Forcages, lai)
158  #     3) Parameters files (allready define through ${SUBMIT_DIR})
159  #     4) Restarts files   (allready define in IGCM_config_Initialize)
160
161  # Here we offer the possibility to redefine R_INIT, R_BC
162  # and PeriodNb through config.card
163  R_INIT=${config_UserChoices_R_INIT:=${R_IN}/INIT}
164  IGCM_debug_Print 2 "(Re)Define R_INIT, R_BC and PeriodNb"
165  IGCM_debug_Print 3 "R_INIT=${R_INIT}"
166  R_BC=${config_UserChoices_R_BC:=${R_IN}/BC}
167  IGCM_debug_Print 3  "R_BC=${R_BC}"
168  PeriodNb=${config_UserChoices_PeriodNb:=${PeriodNb}}
169  IGCM_debug_Print 3  "Loop in main Job with ${PeriodNb} period(s)"
170
171  # Test Archive input/output.
172  IGCM_sys_TestDirArchive ${ARCHIVE}
173  [ $? != 0 ] && IGCM_debug_Exit "IGCM_sys_TestDirArchive"
174  IGCM_sys_TestDirArchive ${R_IN}
175  [ $? != 0 ] && IGCM_debug_Exit "IGCM_sys_TestDirArchive"
176
177  #====================================================
178  #R_SAVE : Job output directory
179  if ( [ ! X${config_UserChoices_SpaceName} = X ] && [ ! X${config_UserChoices_ExperimentName} = X ] ) ; then
180    FreeName=$( echo ${config_UserChoices_JobName} | sed 's/.*_//' )
181    R_SAVE=${R_OUT}/${config_UserChoices_TagName}/${config_UserChoices_SpaceName}/${config_UserChoices_ExperimentName}/${FreeName}
182    R_BUFR=${R_BUF}/${config_UserChoices_TagName}/${config_UserChoices_SpaceName}/${config_UserChoices_ExperimentName}/${FreeName}
183    R_DODS=${config_UserChoices_TagName}/${config_UserChoices_SpaceName}/${config_UserChoices_ExperimentName}/${FreeName}
184  else
185    R_SAVE=${R_OUT}/${config_UserChoices_TagName}/${config_UserChoices_JobName}
186    R_BUFR=${R_BUF}/${config_UserChoices_TagName}/${config_UserChoices_JobName}
187    R_DODS=${config_UserChoices_TagName}/${config_UserChoices_JobName}
188  fi
189
190  if ( ${FirstInitialize} ) ; then
191    IGCM_sys_MkdirArchive ${R_SAVE}
192    IGCM_sys_Mkdir        ${R_BUFR}
193  else
194    IGCM_sys_TestDirArchive ${R_SAVE}
195    [ $? != 0 ] && IGCM_debug_Exit "IGCM_sys_TestDirArchive ${R_SAVE}"
196
197    IGCM_sys_TestDir        ${R_BUFR}
198    [ $? != 0 ] && IGCM_debug_Exit "IGCM_sys_TestDir ${R_BUFR}"
199
200    #Test state of run in run.card
201    IGCM_card_DefineVariableFromOption ${SUBMIT_DIR}/run.card Configuration PeriodState
202   
203    if ( [ ${run_Configuration_PeriodState} != "Start" ] && [ ${run_Configuration_PeriodState} != "Running" ] && [ ${run_Configuration_PeriodState} != "OnQueue" ] && [ ${run_Configuration_PeriodState} != "Continue" ] ) ; then
204      echo
205      IGCM_debug_Print 1 "!! Error in run.card with PeriodState : " ${run_Configuration_PeriodState} "!!"
206      IGCM_debug_Print 1 "Try running ${libIGCM}/clean_month.job to fix this"
207      IGCM_debug_Exit
208      IGCM_debug_Verif_Exit
209    fi
210  fi
211
212  #==================================
213  # Post :
214  IGCM_card_DefineArrayFromSection ${SUBMIT_DIR}/config.card Post
215
216  echo
217  IGCM_debug_Print 1 "DefineArrayFromOption : config_Post"
218
219  for option in ${config_Post[*]} ; do
220    IGCM_card_DefineVariableFromOption ${SUBMIT_DIR}/config.card Post ${option}
221    eval auxprint=\${config_Post_${option}}
222    IGCM_debug_Print 3 "${option} : ${auxprint}"
223  done
224
225  #====================================================
226  # Define REBUILD_DIR : where we store files needing rebuild process
227  if [ X${config_Post_RebuildFromArchive} = Xtrue ] ; then
228    REBUILD_DIR=${R_SAVE}/TMP
229    IGCM_sys_MkdirArchive ${REBUILD_DIR}
230  else
231    REBUILD_DIR=${BIG_DIR}/${config_UserChoices_TagName}/${config_UserChoices_JobName}
232    IGCM_sys_MkdirWork ${REBUILD_DIR}
233  fi
234
235  #====================================================
236  # Experience type : DEB(ug), DEV(elopment), RUN
237  if [ X${JobType} != XRUN ] ; then
238    echo
239    echo "===================================================="
240    echo "libIGCM JOB is NOT in RUN type mode."
241    echo "!! OUTPUT files will NOT be PROTECTED !!"
242    echo "Be carefull : you can ERASE the result of this job !"
243
244    case ${JobType} in
245    DEB)
246      echo "DEBUG mode : activation of 'set -vx' mode."
247      echo "DEBUG mode : no protection for output files."
248      echo "DEBUG mode : if active force asynchronous rebuild frequency to PeriodLength frequency."
249      ;;
250    DEV)
251      echo "DEVelopment mode : no protection for output files."
252      echo "DEVelopment mode : if active force asynchronous rebuild frequency to PeriodLength frequency."
253      ;;
254    esac
255
256    if ( [ X${config_Post_RebuildFrequency} != XNONE ] && [ ${DRYRUN} -eq 0 ] ) ; then
257      if [ X${config_Post_RebuildFrequency} != X${config_UserChoices_PeriodLength} ] ; then
258        echo "------------"
259        echo "WARNING : Job is NOT in RUN mode then we will force REBUILD Frequency"
260        echo "          to PeriodLength : ${config_UserChoices_PeriodLength}"
261        echo "------------"
262        config_Post_RebuildFrequency=${config_UserChoices_PeriodLength}
263      fi
264    fi
265    echo "===================================================="
266    echo
267  fi
268
269  #====================================================
270  #R_OUT_KSH : Storage place for job output
271  #R_OUT_EXE : Storage place for binary used during simulation
272  R_OUT_KSH=${R_SAVE}/Out
273  R_OUT_EXE=${R_SAVE}/Exe
274
275  #====================================================
276  #R_BUF_KSH : Buffer place for job output
277  #R_BUF_EXE : Buffer place for binary used during simulation
278  R_BUF_KSH=${R_BUFR}/Out
279  R_BUF_EXE=${R_BUFR}/Exe
280
281  IGCM_debug_PopStack "IGCM_config_Initialize"
282}
283
284#===================================
285function IGCM_config_Analyse_PeriodLength
286{
287  IGCM_debug_PushStack "IGCM_config_Analyse_PeriodLength"
288
289  typeset i
290
291  # Determine number of day(s) in PeriodLength :
292  case ${config_UserChoices_PeriodLength} in
293  *Y|*y)
294    PeriodLengthInYears=$( echo ${config_UserChoices_PeriodLength} | sed -e 's/[yY]//' ) 
295    IGCM_debug_Print 2 "Number of years for PeriodLength : ${PeriodLengthInYears}"
296    PeriodLengthInDays=0
297    i=0
298    until [ $i -ge $PeriodLengthInYears ] ; do 
299      (( PeriodLengthInDays = PeriodLengthInDays + $( IGCM_date_DaysInYear $(( year + i )) ) )) 
300      (( i=i+1 )) 
301    done 
302    ;;
303  *M|*m)
304    PeriodLengthInMonths=$( echo ${config_UserChoices_PeriodLength} | sed -e 's/[mM]//' ) 
305    IGCM_debug_Print 2 "Number of months for PeriodLength : ${PeriodLengthInMonths}"
306    PeriodLengthInDays=0
307    i=0
308    until [ $i -ge $PeriodLengthInMonths ] ; do
309      if [ $(( month + i )) -lt 13 ] ; then 
310        (( PeriodLengthInDays  = PeriodLengthInDays + $( IGCM_date_DaysInMonth $year $(( month + i )) ) )) 
311      else 
312        (( PeriodLengthInDays  = PeriodLengthInDays + $( IGCM_date_DaysInMonth $year $(( month + i - 12 )) ) )) 
313      fi 
314      (( i=i+1 )) 
315    done 
316    ;;
317  *D|*d) 
318    PeriodLengthInMonths=0
319    PeriodLengthInDays=$( echo ${config_UserChoices_PeriodLength} | sed -e 's/[dD]//' );;
320  *) 
321    IGCM_debug_Exit "IGCM_config_Analyse_PeriodLength " ${config_UserChoices_PeriodLength} " invalid period length : choose in *Y, *M, *D."
322    IGCM_debug_Verif_Exit ;;
323  esac
324
325  IGCM_debug_PopStack "IGCM_config_Analyse_PeriodLength"
326}
327
328#===================================
329function IGCM_config_Check
330{
331  IGCM_debug_PushStack "IGCM_config_Check"
332
333  # If one of the following modulo is not zero :
334  # we will issue an error then explain and exit in
335  # AA_job IGCM_debug_Verif_Exit call before binary submission
336
337  echo
338  IGCM_debug_Print 1 "IGCM_config_Check"
339  echo
340
341  typeset i
342
343  if ( [ ! X${config_Post_RebuildFrequency} = X${NULL_STR} ] && [ ! X${config_Post_RebuildFrequency} = XNONE ] ) ; then
344    AsynchronousRebuild=true
345    IGCM_debug_Print 1 "Asynchronous rebuild has been activated."
346    echo
347    # modulo (RebuildFrequency and PeriodLength/TimeSeriesFrequency/SeasonalFrequency) must be zero
348    IGCM_debug_Print 1 "Check coherence between RebuildFrequency and PeriodLength"
349    IGCM_post_CheckModuloFrequency config_Post_RebuildFrequency config_UserChoices_PeriodLength
350    IGCM_debug_Print 1 "Check coherence between TimeSeriesFrequency and RebuildFrequency"
351    IGCM_post_CheckModuloFrequency config_Post_TimeSeriesFrequency config_Post_RebuildFrequency
352    IGCM_debug_Print 1 "Check coherence between SeasonalFrequency and RebuildFrequency"
353    IGCM_post_CheckModuloFrequency config_Post_SeasonalFrequency config_Post_RebuildFrequency
354  else
355    AsynchronousRebuild=false
356    IGCM_debug_Print 1 "Asynchronous rebuild has not been activated"
357    IGCM_debug_Print 1 "Proceed with standard post-treatment pathway"
358    echo
359    #modulo (TimeSeriesFrequency/SeasonalFrequency and PeriodLenght) must be zero
360    IGCM_debug_Print 1 "Check coherence between TimeSeriesFrequency and PeriodLength"
361    IGCM_post_CheckModuloFrequency config_Post_TimeSeriesFrequency config_UserChoices_PeriodLength
362    IGCM_debug_Print 1 "Check coherence between SeasonalFrequency and PeriodLength"
363    IGCM_post_CheckModuloFrequency config_Post_SeasonalFrequency   config_UserChoices_PeriodLength
364  fi
365
366  #modulo (TimeSeriesFrequency and all Chunck2D) must be zero
367  NbJob=${#CHUNCK2D_SIZE[@]}
368  i=0
369  until [ $i -ge $NbJob ]; do
370    value=${CHUNCK2D_SIZE[${i}]}
371    IGCM_debug_Print 1 "Check coherence between All Chunck2D frequency and TimeSeriesFrequency"
372    IGCM_post_CheckModuloFrequency value config_Post_TimeSeriesFrequency
373    case ${value} in 
374    *Y|*y) ;;
375    *)  IGCM_debug_Print 1 "All ChunckJob2D frequency must be expressed in year *Y|*y in comp.card"
376      IGCM_debug_Exit "This will stop the job" ;;
377    esac
378    (( i=i+1 ))
379  done
380
381  #modulo (TimeSeriesFrequency and all Chunck3D) must be zero
382  NbJob=${#CHUNCK3D_SIZE[@]}
383  i=0
384  until [ $i -ge $NbJob ]; do
385    value=${CHUNCK3D_SIZE[${i}]}
386    IGCM_debug_Print 1 "Check coherence between All Chunck3D frequency and TimeSeriesFrequency"
387    IGCM_post_CheckModuloFrequency value config_Post_TimeSeriesFrequency
388    case ${value} in 
389    *Y|*y) ;;
390    *)  IGCM_debug_Print 1 "All ChunckJob3D frequency must be expressed in year *Y|*y in comp.card"
391      IGCM_debug_Exit "This will stop the job" ;;
392    esac
393    (( i=i+1 ))
394  done
395
396  IGCM_debug_PopStack "IGCM_config_Check"
397}
398
399#===================================
400function IGCM_config_PeriodStart
401{
402  IGCM_debug_PushStack "IGCM_config_PeriodStart"
403
404  echo
405  IGCM_debug_Print 1 "IGCM_config_PeriodStart"
406  echo
407
408  if ( ${FirstInitialize} ) ; then
409    #================================================#
410    #         Initialize date/period information     #
411    #================================================#
412
413    IGCM_date_GetYearMonthDay $DateBegin year month day
414    IGCM_config_Analyse_PeriodLength
415
416    eval PeriodDateBegin=${DateBegin} > /dev/null 2>&1
417    PeriodDateEnd=$( IGCM_date_AddDaysToGregorianDate ${DateBegin} $(( ${PeriodLengthInDays} - 1 )) )
418    eval CumulPeriod=1 > /dev/null 2>&1
419
420    #=================================================#
421    #              Write updated run.card             #
422    #=================================================#
423
424    #Correct run.card Configuration for this period
425    IGCM_card_WriteOption ${SUBMIT_DIR}/run.card Configuration PeriodDateBegin ${PeriodDateBegin}
426    IGCM_card_WriteOption ${SUBMIT_DIR}/run.card Configuration PeriodDateEnd ${PeriodDateEnd}
427    IGCM_card_WriteOption ${SUBMIT_DIR}/run.card Configuration CumulPeriod ${CumulPeriod}
428    if [ X$( grep "SubmitPath" ${SUBMIT_DIR}/run.card ) != X ] ; then
429      IGCM_card_WriteOption ${SUBMIT_DIR}/run.card Configuration SubmitPath ${SUBMIT_DIR}
430    fi
431
432    IGCM_card_WriteOption ${SUBMIT_DIR}/run.card Configuration PeriodState "Running"
433   
434  else
435    #================================================#
436    #         The file run.card allready exist       #
437    #================================================#
438
439    #Test state of run in run.card
440    IGCM_card_DefineVariableFromOption ${SUBMIT_DIR}/run.card Configuration PeriodState
441    if ( [ ${run_Configuration_PeriodState} != "Running" ] && [ ${run_Configuration_PeriodState} != "OnQueue" ] && [ ${run_Configuration_PeriodState} != "Continue" ] ) ; then
442      echo
443      IGCM_debug_Print 1 "!! Error in run.card with PeriodState : " ${run_Configuration_PeriodState} "!!"
444      IGCM_debug_Print 1 "Try running ${libIGCM}/clean_month.job to fix this"
445      echo
446      IGCM_debug_Exit
447      IGCM_debug_Verif_Exit
448    fi
449
450    #===================================#
451    #        Read updated run.card      #
452    #===================================#
453
454    IGCM_card_DefineVariableFromOption ${SUBMIT_DIR}/run.card Configuration OldPrefix
455    IGCM_card_DefineVariableFromOption ${SUBMIT_DIR}/run.card Configuration PeriodDateBegin
456    IGCM_card_DefineVariableFromOption ${SUBMIT_DIR}/run.card Configuration PeriodDateEnd
457    IGCM_card_DefineVariableFromOption ${SUBMIT_DIR}/run.card Configuration CumulPeriod
458
459    PeriodDateBegin=$( IGCM_date_ConvertFormatToGregorian ${run_Configuration_PeriodDateBegin} )
460    PeriodDateEnd=$( IGCM_date_ConvertFormatToGregorian ${run_Configuration_PeriodDateEnd} )
461    eval CumulPeriod="${run_Configuration_CumulPeriod}" > /dev/null 2>&1
462
463    LastPeriodDateEnd=$( echo ${run_Configuration_OldPrefix} | sed -e "s/${config_UserChoices_JobName}_//" )
464
465    typeset LastDate
466    set +A LastDate -- $( echo ${LastPeriodDateEnd} | sed -e "s/\([0-9]\{${dY}\}\)\([0-9]\{2\}\)\([0-9]\{2\}\)/\1 \2 \3/" )
467    LastYearDateEnd=${LastDate[0]}
468    LastMonthDateEnd=${LastDate[1]}
469    LastDayDateEnd=${LastDate[2]}
470
471    if [ ${Period} = 1 ]; then
472      # save last Job output
473      typeset LastPeriod iLastPeriod Last_Script_Output_Name
474      (( LastPeriod=CumulPeriod-PeriodNb ))
475      iLastPeriod=$( printf "%06d" ${LastPeriod} )
476      Last_Script_Output_Name="${Script_Output_Prefix}_${config_UserChoices_JobName}.${iLastPeriod}"
477      Last_run_card="run.card.${iLastPeriod}"
478      #eval ls -l ${SUBMIT_DIR}/${Last_Script_Output_Name}
479      #eval IGCM_sys_Put_Out ${SUBMIT_DIR}/${Last_Script_Output_Name} ${R_BUF_KSH}/${Last_Script_Output_Name} > /dev/null 2>&1
480      IGCM_debug_Print 2 "Try to save previous ksh job output"
481      IGCM_sys_Cd ${SUBMIT_DIR}/
482      IGCM_sys_PutBuffer_Out ${Last_Script_Output_Name} ${R_BUF_KSH}/${Last_Script_Output_Name}.$$ rw
483
484      IGCM_card_CheckConflict run.card
485      IGCM_sys_PutBuffer_Out ${SUBMIT_DIR}/run.card ${R_BUF_KSH}/${Last_run_card}.$$ rw
486
487      IGCM_sys_Cd ${RUN_DIR}
488    else
489      unset FileToBeDeleted
490    fi
491
492    IGCM_date_GetYearMonthDay $PeriodDateBegin year month day
493    IGCM_config_Analyse_PeriodLength
494
495    IGCM_card_WriteOption ${SUBMIT_DIR}/run.card Configuration PeriodState "Running"
496
497  fi   
498  OldPrefix=${config_UserChoices_JobName}_${PeriodDateEnd}
499
500  # BEGIN: SHOULD GO IN A FUNCTION FROM libIGCM_date.ksh
501  # Compute year_m1 and year_p1 (year minus 1Y and year plus 1Y)
502  year_m1=$(( year - 1 ))
503  year_p1=$(( year + 1 ))       
504  # Compute month_m1 (month minus 1M)
505  # Compute yyyymm_m1 (yyyymm minus 1M)
506  month_m1=$(( month - 1 ))
507  if [ ${month_m1} = 0 ]; then
508    month_m1=12
509    yyyymm_m1=${year_m1}12
510  elif [ ${month_m1} -le 9 ]; then
511    month_m1=0${month_m1}
512    yyyymm_m1=${year}${month_m1}
513  else
514    yyyymm_m1=${year}${month_m1}
515  fi
516  # Compute month_p1 (month plus 1M)
517  # Compute yyyymm_p1 (yyyymm plus 1M)
518  month_p1=$(( month + 1 ))
519  if [ ${month_p1} = 13 ]; then
520    month_p1=01
521    yyyymm_p1=${year_p1}01
522  elif [ ${month_p1} -le 9 ]; then
523    month_p1=0${month_p1}
524    yyyymm_p1=${year}${month_p1}
525  else
526    yyyymm_p1=${year}${month_p1}
527  fi
528  #IGCM_debug_Print 1 "jg 1 month_m1 = ${month_m1} month_p1 = ${month_p1} "
529  #IGCM_debug_Print 1 "jg 1 calculate yyyymm_m1 = ${yyyymm_m1} "
530  #IGCM_debug_Print 1 "jg 1 calculate yyyymm_p1 = ${yyyymm_p1} "
531
532  # END: SHOULD GO IN A FUNCTION FROM libIGCM_date.ksh
533
534  #===================================================================#
535  # Prepare variables available for ${COMP}.card and ${COMP}.driver   #
536  #             But available to any son functions                    #
537  #===================================================================#
538
539  # Period Length In Days between DateBegin and DateCurrent (at end of period == PeriodDateEnd !)
540  (( SimulationLengthInDays = $( IGCM_date_DaysBetweenGregorianDate ${PeriodDateEnd} ${DateBegin} ) + 1 ))
541
542  # Debug Print :
543  IGCM_debug_Print 1 "IGCM_config_PeriodStart : Before Execution"
544  IGCM_debug_Print 1 "Year of simulation      : ${year}"
545  IGCM_debug_Print 1 "Month of simulation     : ${month}"
546  IGCM_debug_Print 1 "PeriodLengthInDays      : ${PeriodLengthInDays}"
547  IGCM_debug_Print 1 "PeriodDateBegin         : ${PeriodDateBegin}"
548  IGCM_debug_Print 1 "PeriodDateEnd           : ${PeriodDateEnd}"
549  IGCM_debug_Print 1 "SimulationLengthInDays  : ${SimulationLengthInDays}"
550  IGCM_debug_Print 1 "ExperienceLengthInDays  : ${ExperienceLengthInDays}"
551
552  #================================================================#
553  #         Prepare variables available for comp_finalyze          #
554  #================================================================#
555
556  # Period for save files
557  eval DatesPeriod=${PeriodDateBegin}_${PeriodDateEnd} > /dev/null 2>&1
558
559  # Prefix for save files of this period
560  eval PREFIX=${config_UserChoices_JobName}_${DatesPeriod}  > /dev/null 2>&1
561
562  # List of files that will be deleted in RUN_DIR after run
563  [ -f stack ] && FileToBeDeleted[0]="stack"
564
565  # Test if the same run as already been saved :
566  if [ X${JobType} = XRUN ] ; then
567    if [ ${DRYRUN} -le 0 ] ; then
568      if ( IGCM_sys_TestFileBuffer ${R_BUF_KSH}/${PREFIX}_${Exe_Output} ) ; then
569        IGCM_debug_Exit "IGCM_config_PeriodStart" "You are currently RErunning an old job."
570        IGCM_debug_Print 1 "Because of readonly permissions, you can't RErun a job when saved files"
571        IGCM_debug_Print 1 " are still in the ARCHIVE directory. You must deleted those files, or "
572        IGCM_debug_Print 1 " the whole ${R_SAVE} tree. See clean_month.job in ${libIGCM} directory."
573        IGCM_debug_Print 1 " This exit has been initiated because at least ${R_BUF_KSH}/${PREFIX}_${Exe_Output} exists."
574        IGCM_debug_Verif_Exit
575      fi
576    fi
577  else
578    if ( IGCM_sys_TestFileBuffer ${R_BUF_KSH}/${PREFIX}_${Exe_Output} ) ; then
579      IGCM_debug_Print 1 "IGCM_config_PeriodStart" "RErun an old job. Allowed in DEBUG or DEV mode."
580    fi
581  fi
582
583  ExecutionFail=false
584
585  IGCM_debug_PopStack "IGCM_config_PeriodStart"
586}
587
588#===================================
589function IGCM_config_SaveSourceModifications
590{
591  IGCM_debug_PushStack "IGCM_config_SaveSourceModifications"
592
593  typeset ExeOutDateMax listVarEnv
594  ExeOutDateMax=$1
595
596  listVarEnv="ExeOutDateMax,R_OUT_EXE,PREFIX,SUBMIT_DIR"
597  IGCM_sys_RshMaster "\
598    . ${libIGCM}/libIGCM_sys/libIGCM_sys.ksh; \
599    export ExeOutDateMax=${ExeOutDateMax};\
600    export R_OUT_EXE=${R_OUT_EXE};\
601    export PREFIX=${PREFIX};\
602    export SUBMIT_DIR=${SUBMIT_DIR};\
603    export listVarEnv=${listVarEnv};\
604    Script_Output=out_SaveSourceModifications;\
605    IGCM_sys_Qsub ${libIGCM}/SaveSourceModifications.job ${ExeOutDateMax} ${R_OUT_EXE} ${PREFIX} ${SUBMIT_DIR}"
606
607  IGCM_debug_PopStack "IGCM_config_SaveSourceModifications"
608}
609
610#===================================
611function IGCM_config_PeriodEnd
612{
613  IGCM_debug_PushStack "IGCM_config_PeriodEnd"
614
615  echo
616  IGCM_debug_Print 1 "IGCM_config_PeriodEnd"
617  echo
618
619  #==================================#
620  #         Save Job output          #
621  #==================================#
622  IGCM_sys_PutBuffer_Out ${Exe_Output} ${R_BUF_KSH}/${PREFIX}_${Exe_Output}
623  eval FileToBeDeleted[${#FileToBeDeleted[@]}]="${Exe_Output}"
624
625      IGCM_card_CheckConflict run.card
626      IGCM_sys_PutBuffer_Out ${SUBMIT_DIR}/run.card ${R_BUF_KSH}/run.card rw
627
628      IGCM_debug_Print 1 "Check components binary : size and creation date"
629
630      typeset LS_comp LS_bin ExeDate ExeCpuLog NextExeSize LastCompExeSize
631      typeset comp i   
632      typeset ExeNameIn ExeNameOut UpdateExe ExeSecDateMax
633
634      #==================================#
635      #        Get last Exe Size         #
636      #==================================#
637
638      (( i=0 ))
639      if ( ${FirstInitialize} ) ; then
640        run_Log_LastExeSize=""
641        for comp in ${config_ListOfComponents[*]} ; do
642          run_Log_LastExeSize[$i]=0
643          (( i=i+1 ))
644        done
645      else
646        IGCM_card_DefineArrayFromOption ${SUBMIT_DIR}/run.card Log LastExeSize
647      fi
648      #==================================#
649      #         And Build ExeDate        #
650      #==================================#
651
652      # ExeDate = ATM_Jun_12_09:34-SRF_Jun_12_09:34-OCE_Jun_12_09:34-ICE_Jun_12_09:34-CPL_Jun_12_09:33
653      # Would be nice to have next line but no way to format ls output (need to ls -l --time-style "+%Y-%m-%dT%H:%M")
654      # ExeDate = ATM_2009-06-12T09:34+SRF_2009-06-12T09:34+OCE_2009-06-12T09:34+ICE_2009-06-12T09:34+CPL_2009-06-12T09:34
655      ExeDate=""
656      NextExeSize="( "
657      (( i=0 ))
658      UpdateExe=false
659      (( ExeSecDateMax = 0 ))
660      for comp in ${config_ListOfComponents[*]} ; do
661
662        IGCM_debug_Print 3 ${comp}
663
664        eval ExeNameIn=\${config_Executable_${comp}[0]}
665        eval ExeNameOut=\${config_Executable_${comp}[1]}
666        # Only if we really have an executable for the component :
667        if [ X${ExeNameIn} = X\"\" ] ; then
668          # If there is no exe file for this component
669          (( ExeSize=0 ))
670        else
671          eval LS_bin=${R_EXE}/${ExeNameIn}
672          IGCM_sys_FileSize ${LS_bin} ExeSize
673
674          set +A LS_comp -- $( LC_TIME=en_US ls -l ${LS_bin} )
675          if [ X${ExeDate} = X ] ; then 
676            # First component exe date
677            ExeDate=${comp}_${LS_comp[5]}_${LS_comp[6]}
678          else
679            ExeDate=${ExeDate}-${comp}_${LS_comp[5]}_${LS_comp[6]}
680          fi
681          ExeDate=${ExeDate}_${LS_comp[7]}
682        fi
683
684        if [ ${i} -eq 0 ] ; then
685          # First component
686          NextExeSize="( "${ExeSize}
687        else
688          NextExeSize=${NextExeSize}", "${ExeSize}
689        fi
690        eval LastCompExeSize=${run_Log_LastExeSize[$i]}
691        (( i=i+1 ))
692
693        if [ ${ExeSize} -ne ${LastCompExeSize} ] ; then
694          if ( ${FirstInitialize} ) ; then
695            IGCM_debug_Print 1 "Save first ${ExeNameIn} in ${R_OUT_EXE} !"
696          else
697            IGCM_debug_Print 1 "${ExeNameIn} has changed in ${R_EXE} !"
698            IGCM_debug_Print 1 "Save latest ${ExeNameIn} in ${R_OUT_EXE} !"
699            eval FileToBeDeleted[${#FileToBeDeleted[@]}]=${ExeNameOut}
700          fi
701          eval IGCM_sys_Put_Out ${ExeNameOut} ${R_OUT_EXE}/${PREFIX}_${ExeNameIn} rw
702          UpdateExe=true
703
704          IGCM_sys_GetDate_FichWork ${LS_bin} ExeSecDate
705          if [ $ExeSecDateMax -lt $ExeSecDate ] ; then
706            ExeSecDateMax=$ExeSecDate
707          fi
708        fi
709      done
710
711# SD : switch off for now
712#      if ( ${UpdateExe} ) ; then
713#       echo "Launch SaveSourceModifications."
714#       IGCM_config_SaveSourceModifications ${ExeSecDateMax}
715#      fi
716
717      NextExeSize=${NextExeSize}" )"
718      IGCM_card_WriteOption ${SUBMIT_DIR}/run.card Log LastExeSize "${NextExeSize}"
719
720      if [ ${DRYRUN} -le 1 ] ; then
721        tail -1500 ${Exe_Output} > ${Exe_Output}_tail.txt
722        ExeCpuLog=$( gawk -f ${libIGCM}/libIGCM_sys/IGCM_add_out.awk ${Exe_Output}_tail.txt )
723        RET=$?
724        if [ $RET -eq 0 ] ; then
725          # ExeCpuLog variable contents 5 fields
726          echo "${CumulPeriod} ${PeriodDateBegin} ${PeriodDateEnd} ${ExeCpuLog} ${ExeDate}" |   \
727            gawk '{printf("# %11d | %15s | %15s | %19s | %19s | %15.5f | %15.5f | %15.5f | %s\n", \
728            $1,$2,$3,$4,$5,$6,$7,$8,$9)}' >> ${SUBMIT_DIR}/run.card
729        fi
730        eval FileToBeDeleted[${#FileToBeDeleted[@]}]="${Exe_Output}_tail.txt"
731      fi
732
733      # All was right ? no ? then we stop.
734      IGCM_debug_Verif_Exit
735
736      # If all was OK, we can delete all files not necessary for next Job
737      echo
738      IGCM_debug_Print 1 "Files that will be deleted before next period-run : "
739
740      if [ ${DRYRUN} -le 2 ] ; then
741        for f in ${FileToBeDeleted[@]} ; do [ -f ${f} ] && ls -la $f ; [ -f ${f} ] && rm -f $f ; done
742      else
743        echo ${FileToBeDeleted[@]}
744      fi
745
746      #=================================================#
747      #         Modification of libIGCM behaviour       #
748      #=================================================#
749
750      # To use this function, one must copy libIGCM.card from ${libIGCM} directory
751      # and put it in ${SUBMIT_DIR} directory. After modifications of ${SUBMIT_DIR}/libIGCM.card,
752      # variables define inside [UserChanges] will be modified for next Period of libIGCM main loop.
753      if [ -f ${SUBMIT_DIR}/libIGCM.card ] ; then
754        echo
755        echo "########################################################################"
756        echo "!!!                 Modification of libIGCM behaviour                !!!"
757        echo
758
759        IGCM_debug_Print 1 "DefineArrayFromOption  : libIGCM_UserChanges in libIGCM.card"
760        IGCM_card_DefineArrayFromSection ${SUBMIT_DIR}/libIGCM.card UserChanges
761        IGCM_debug_Print 2 "libIGCM_UserChanges" ${libIGCM_UserChanges[*]}
762
763        # Special treatments for libIGCM internals
764        for option in ${libIGCM_UserChanges[*]} ; do
765          IGCM_card_DefineVariableFromOption ${SUBMIT_DIR}/libIGCM.card UserChanges ${option}
766
767          echo "We will change : ${option}."
768          eval echo "Previous value : " \${${option}}
769          eval echo "Change to : " \${libIGCM_UserChanges_${option}}
770         
771          eval ${option}=\${libIGCM_UserChanges_${option}}
772
773          case ${option} in
774          config_UserChoices_DateEnd)
775          IGCM_debug_PrintVariables 1 config_UserChoices_DateEnd
776          DateEnd=$( IGCM_date_ConvertFormatToGregorian ${config_UserChoices_DateEnd} )
777
778          # Period Length In Days between DateBegin and DateEnd
779          (( ExperienceLengthInDays=$( IGCM_date_DaysBetweenGregorianDate ${DateEnd} ${DateBegin} )  + 1 ))
780          if [ ${ExperienceLengthInDays} -lt 0 ] ; then
781            IGCM_debug_Print 1 "Problem with dates in libIGCM.card : ${DateEnd} < ${DateBegin} ! You must check that."
782            IGCM_debug_Exit "IGCM_PeriodEnd" " Wrong Dates."
783            IGCM_debug_Verif_Exit
784          fi
785          ;;
786          config_UserChoices_PeriodLength)
787        IGCM_debug_Print 1  "Change config_UserChoices_PeriodLength=${config_UserChoices_PeriodLength}"
788        ;;
789        PeriodNb)
790              IGCM_debug_Print 1  "Loop in main Job with ${PeriodNb} period(s)"
791              ;;
792              config_Post_RebuildFrequency)
793            IGCM_debug_Print 1  "Change config_Post_RebuildFrequency=${config_Post_RebuildFrequency} : IGCM_post_Configure"
794            IGCM_post_Configure
795            ;;
796            config_Post_TimeSeriesFrequency)
797    IGCM_debug_Print 1  "Change config_Post_TimeSeriesFrequency = ${config_Post_TimeSeriesFrequency} : IGCM_post_Initialize"
798    IGCM_post_Configure
799    ;;
800    config_Post_SeasonalFrequency)
801  IGCM_debug_Print 1  "Change config_Post_SeasonalFrequency = ${config_Post_SeasonalFrequency} : IGCM_post_Initialize"
802  IGCM_post_Configure
803  ;;
804  esac
805  done
806
807  echo
808  echo "########################################################################"
809  echo
810  fi
811
812  #=================================================#
813  #         Determine next computed period          #
814  #=================================================#
815
816  PeriodDateBegin=$( IGCM_date_AddDaysToGregorianDate ${PeriodDateEnd} 1 )
817  IGCM_date_GetYearMonthDay $PeriodDateBegin year month day
818  year_m1=$(( year - 1 ))
819  year_p1=$(( year + 1 ))
820  IGCM_config_Analyse_PeriodLength
821  PeriodDateEnd=$( IGCM_date_AddDaysToGregorianDate ${PeriodDateBegin} $(( ${PeriodLengthInDays} - 1 )) )
822
823  # Debug Print :
824  echo
825  IGCM_debug_Print 1 "IGCM_config_PeriodEnd : Preparing Next Execution"
826  IGCM_debug_Print 1 "PeriodDateBegin       : ${PeriodDateBegin}"
827  IGCM_debug_Print 1 "PeriodDateEnd         : ${PeriodDateEnd}"
828  IGCM_debug_Print 1 "PeriodLengthInDays    : ${PeriodLengthInDays}"
829
830  PeriodDateBegin=$( IGCM_date_ConvertFormatToHuman ${PeriodDateBegin} )
831  PeriodDateEnd=$( IGCM_date_ConvertFormatToHuman ${PeriodDateEnd} )
832
833  (( CumulPeriod = CumulPeriod + 1 ))
834
835  # Debug Print :
836  echo
837  IGCM_debug_Print 3 "PeriodDateBegin Human : ${PeriodDateBegin}"
838  IGCM_debug_Print 3 "PeriodDateEnd Human   : ${PeriodDateEnd}"
839  IGCM_debug_Print 3 "CumulPeriod           : ${CumulPeriod}"
840
841  #=================================================#
842  #             Write updated run.card              #
843  #=================================================#
844
845  IGCM_card_WriteOption ${SUBMIT_DIR}/run.card Configuration OldPrefix ${OldPrefix}
846  IGCM_card_WriteOption ${SUBMIT_DIR}/run.card Configuration PeriodDateBegin ${PeriodDateBegin}
847  IGCM_card_WriteOption ${SUBMIT_DIR}/run.card Configuration PeriodDateEnd ${PeriodDateEnd}
848  IGCM_card_WriteOption ${SUBMIT_DIR}/run.card Configuration CumulPeriod ${CumulPeriod}
849
850  if ( ${FirstInitialize} ) ; then
851    # It's no more the first time
852    FirstInitialize=false
853  fi
854
855  IGCM_debug_PopStack "IGCM_config_PeriodEnd"
856}
857
858#===================================
859function IGCM_config_Finalize
860{
861  IGCM_debug_PushStack "IGCM_config_Finalize"
862
863  echo
864  IGCM_debug_Print 1 "IGCM_config_Finalize"
865  echo
866
867  if [ ${SimulationLengthInDays} -ge ${ExperienceLengthInDays} ] ; then
868    #==========================#
869    # End of entire simulation #
870    #==========================#
871
872    # Mail notification
873    IGCM_sys_SendMail
874
875    #
876    IGCM_card_WriteOption ${SUBMIT_DIR}/run.card Configuration PeriodState "Completed"
877    IGCM_debug_Print 1 "Normal End of computation."
878    if ( $DEBUG_debug ) ; then
879      echo
880      IGCM_debug_Print 1 "Your files on ${R_SAVE} :"
881      IGCM_sys_Tree ${R_SAVE}
882
883      IGCM_debug_Print 1 "Your files on ${R_BUFR} :"
884      IGCM_sys_Tree ${R_BUFR}
885    fi
886  else
887    #=================#
888    # Submit next job #
889    #=================#
890
891    IGCM_card_WriteOption ${SUBMIT_DIR}/run.card Configuration PeriodState "OnQueue"
892
893    # Name of next Ksh Script output :
894    eval Script_Output="${Script_Output_Prefix}_${config_UserChoices_JobName}.$( printf "%06d" ${CumulPeriod} )"
895
896    IGCM_debug_Print 1 "Submit next job"
897    # SUBMIT NEXT JOB from SUBMIT_DIR and come back in RUN_DIR
898    IGCM_sys_Cd ${SUBMIT_DIR}
899    # Keep only the 5 latest ${Script_Output_Prefix}_${config_UserChoices_JobName}
900    ScriptTot=$( ls ${Script_Output_Prefix}_${config_UserChoices_JobName}.?????? 2>/dev/null | wc -l )
901    [ ${ScriptTot} -gt 5 ] && rm -f $( ls ${Script_Output_Prefix}_${config_UserChoices_JobName}.?????? | head -$(( ${ScriptTot} - 5 )) )
902    # Submit next job and come back
903    IGCM_sys_Qsub ${SUBMIT_DIR}/Job_${config_UserChoices_JobName}
904    IGCM_sys_Cd -
905  fi
906
907  # Supress Non Deleted Boundary files
908  if [ ${DRYRUN} -le 2 ] ; then
909    IGCM_comp_DelFixeBoundaryFiles
910    ls -la
911  fi
912 
913  # Clean ${RUN_DIR}=${RUN_DIR_PATH}/${config_UserChoices_TagName}/${config_UserChoices_JobName}
914  # Only for production run (No clean up in DEV or DEB mode)
915  # and command sent from .. directory.
916  IGCM_sys_Cd ..
917  [ X${JobType} = XRUN ] && IGCM_sys_Rm -rf ${RUN_DIR}
918
919  IGCM_debug_PopStack "IGCM_config_Finalize"
920}
921
922#===================================
Note: See TracBrowser for help on using the repository browser.