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

Last change on this file since 1516 was 1516, checked in by acosce, 4 years ago

add initialization to NONE for rebuildFrequency if we don't find it in config.card
solve to #347

  • 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: 55.1 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_CommonConfiguration
16{
17  IGCM_debug_PushStack "IGCM_config_CommonConfiguration" $@
18
19  # Debug Print :
20  [ ${Verbosity} -gt 0 ] && echo
21  IGCM_debug_Print 1 "IGCM_config_CommonConfiguration" $@
22
23  # config.card path
24  configCardPath=$1
25
26  #==================================
27  typeset option auxprint
28
29  #==================================
30  # Read UserChoices section:
31  [ ${Verbosity} -gt 0 ] && echo
32  IGCM_debug_Print 1 "DefineArrayFromOption  : config_UserChoices"
33
34  IGCM_card_DefineArrayFromSection ${configCardPath} UserChoices
35  for option in ${config_UserChoices[*]} ; do
36    IGCM_card_DefineVariableFromOption ${configCardPath} UserChoices ${option}
37    eval auxprint=\${config_UserChoices_${option}}
38    IGCM_debug_Print 3 "${option} : ${auxprint}"
39  done
40
41  # Set variables with shorter names on some variables which 
42  # are used in the executable name in config.card
43  ResolAtm=${config_UserChoices_ResolAtm}
44  ResolOce=${config_UserChoices_ResolOce}
45  ConfChem=${config_UserChoices_ConfChem}
46  OptMode=${config_UserChoices_OptMode}
47
48  #==================================
49  # Read Ensemble section:
50  [ ${Verbosity} -gt 0 ] && echo
51  IGCM_debug_Print 1 "DefineArrayFromOption  : config_Ensemble"
52
53  IGCM_card_DefineArrayFromSection ${configCardPath} Ensemble
54  for option in ${config_Ensemble[*]} ; do
55    IGCM_card_DefineVariableFromOption ${configCardPath} Ensemble ${option}
56    eval auxprint=\${config_Ensemble_${option}}
57    IGCM_debug_Print 3 "${option} : ${auxprint}"
58  done
59
60  #==================================
61  # Read Post section:
62  [ ${Verbosity} -gt 0 ] && echo
63  IGCM_debug_Print 1 "DefineArrayFromOption : config_Post"
64
65  IGCM_card_DefineArrayFromSection ${configCardPath} Post
66  for option in ${config_Post[*]} ; do
67    IGCM_card_DefineVariableFromOption ${configCardPath} Post ${option}
68    eval auxprint=\${config_Post_${option}}
69    IGCM_debug_Print 3 "${option} : ${auxprint}"
70  done
71  [ ${Verbosity} -gt 0 ] && echo
72
73  #==================================
74  # Define default value to keep compatibility with previous card: means before changes due to TGCC
75  # Apply some overrules to ensure proper usage of computing centres resources
76  #
77
78  # if RebuildFrequency is not define in config.card - we initilize it to NONE
79  if [ X${config_Post_RebuildFrequency} = X ] ; then
80      config_Post_RebuildFrequency=NONE
81  fi
82
83  if [ X${PackDefault} = Xtrue ] ; then
84    if [ X${config_UserChoices_SpaceName} = XTEST ]; then
85      # TEST simulations will not be packed and will stay on SCRATCHDIR filesystem
86      IGCM_debug_Print 1 "SpaceName=TEST. OVERRULE PackFrequency to NONE"
87      config_Post_PackFrequency=NONE
88    else
89      # Default to RebuildFrequency if nothing has been set up related to PackFrequency
90      [ X${config_Post_PackFrequency} = X ] && config_Post_PackFrequency=${config_Post_RebuildFrequency}
91    fi
92  else
93    # If we DO NOT apply pack in this computing center
94    config_Post_PackFrequency=NONE
95  fi
96
97  #====================================================
98  # Define ARCHIVE : Dedicated to large files
99  # Define STORAGE : Dedicated to small/medium files
100  # Define R_OUT   : Output tree located on ARCHIVE
101  # Define R_BUF   : Output tree located on STORAGE (files waiting treatment, or file lcoation when SpaceName=!PROD)
102  # Define R_FIG   : Output tree located on STORAGE hosting figures (monitoring and atlas, and/or small files)
103  # Define R_TMP   : A temporary space used by IGCM_debug_send_AMQP_msg__MAILTUNNEL. Must be persistent in between jobs
104  IGCM_sys_defineArchives
105
106  #====================================================
107  # R_SAVE : Job output directory
108  # R_BUFR : Job output buffered directory
109  # R_CMIP : Job output directory for CMIP6 standard files
110
111  if ( [ ! X${config_UserChoices_SpaceName} = X ] && [ ! X${config_UserChoices_ExperimentName} = X ] ) ; then
112    FreeName=$( echo ${config_UserChoices_JobName} | sed 's/.*_//' )
113    if ( [ ! X${config_Ensemble_EnsembleName} = X ] && [ ! X${config_Ensemble_EnsembleDate} = X ] ) ; then
114      R_SAVE=${R_OUT}/${config_UserChoices_TagName}/${config_UserChoices_SpaceName}/${config_UserChoices_ExperimentName}/${config_Ensemble_EnsembleName}/${config_Ensemble_EnsembleDate}/${FreeName}
115      R_FIGR=${R_FIG}/${config_UserChoices_TagName}/${config_UserChoices_SpaceName}/${config_UserChoices_ExperimentName}/${config_Ensemble_EnsembleName}/${config_Ensemble_EnsembleDate}/${FreeName}
116      R_BUFR=${R_BUF}/${config_UserChoices_TagName}/${config_UserChoices_SpaceName}/${config_UserChoices_ExperimentName}/${config_Ensemble_EnsembleName}/${config_Ensemble_EnsembleDate}/${FreeName}
117      R_DODS=${config_UserChoices_TagName}/${config_UserChoices_SpaceName}/${config_UserChoices_ExperimentName}/${config_Ensemble_EnsembleName}/${config_Ensemble_EnsembleDate}/${FreeName}
118      R_CMIP=${CMIP6_BUF}/${config_UserChoices_TagName}/${config_UserChoices_SpaceName}/${config_UserChoices_ExperimentName}/${config_Ensemble_EnsembleName}/${config_Ensemble_EnsembleDate}/${FreeName}
119    else
120      R_SAVE=${R_OUT}/${config_UserChoices_TagName}/${config_UserChoices_SpaceName}/${config_UserChoices_ExperimentName}/${FreeName}
121      R_FIGR=${R_FIG}/${config_UserChoices_TagName}/${config_UserChoices_SpaceName}/${config_UserChoices_ExperimentName}/${FreeName}
122      R_BUFR=${R_BUF}/${config_UserChoices_TagName}/${config_UserChoices_SpaceName}/${config_UserChoices_ExperimentName}/${FreeName}
123      R_DODS=${config_UserChoices_TagName}/${config_UserChoices_SpaceName}/${config_UserChoices_ExperimentName}/${FreeName}
124      R_CMIP=${CMIP6_BUF}/${config_UserChoices_TagName}/${config_UserChoices_SpaceName}/${config_UserChoices_ExperimentName}/${FreeName}
125    fi
126  else
127    if ( [ ! X${config_Ensemble_EnsembleName} = X ] && [ ! X${config_Ensemble_EnsembleDate} = X ] ) ; then
128      R_SAVE=${R_OUT}/${config_UserChoices_TagName}/${config_Ensemble_EnsembleName}/${config_Ensemble_EnsembleDate}/${config_UserChoices_JobName}
129      R_FIGR=${R_FIG}/${config_UserChoices_TagName}/${config_Ensemble_EnsembleName}/${config_Ensemble_EnsembleDate}/${config_UserChoices_JobName}
130      R_BUFR=${R_BUF}/${config_UserChoices_TagName}/${config_Ensemble_EnsembleName}/${config_Ensemble_EnsembleDate}/${config_UserChoices_JobName}
131      R_DODS=${config_UserChoices_TagName}/${config_Ensemble_EnsembleName}/${config_Ensemble_EnsembleDate}/${config_UserChoices_JobName}
132    else
133      R_SAVE=${R_OUT}/${config_UserChoices_TagName}/${config_UserChoices_JobName}
134      R_FIGR=${R_FIG}/${config_UserChoices_TagName}/${config_UserChoices_JobName}
135      R_BUFR=${R_BUF}/${config_UserChoices_TagName}/${config_UserChoices_JobName}
136      R_DODS=${config_UserChoices_TagName}/${config_UserChoices_JobName}
137    fi
138  fi
139
140  #====================================================
141  # Define R_OUT_KSH : Storage place for job output
142  # Define R_OUT_EXE : Storage place for binary used during simulation
143  R_OUT_KSH=${R_SAVE}/Out
144  R_OUT_EXE=${R_SAVE}/Exe
145
146  #====================================================
147  # Define R_BUF_KSH : Buffer place for job output
148  # Define R_BUF_EXE : Buffer place for binary used during simulation
149  R_BUF_KSH=${R_BUFR}/Out
150  R_BUF_EXE=${R_BUFR}/Exe
151
152  #====================================================
153  # Define REBUILD_DIR : where we store files needing rebuild process
154  REBUILD_DIR=${R_BUFR}/REBUILD
155  if [ ! X${TaskType} = Xchecking ] ; then
156    IGCM_sys_MkdirWork ${REBUILD_DIR}
157  fi
158
159  #====================================================
160  # DodsCopy : apply default value if not defined
161  if ( [ X${config_Post_DodsCopy} = X${NULL_STR} ] || [ X${config_Post_DodsCopy} = X ] ) ; then
162    config_Post_DodsCopy=TRUE
163  fi
164
165  #====================================================
166  # AtlasIPSL : apply default value if not defined
167  if ( [ X${config_Post_AtlasIPSL} = X${NULL_STR} ] || [ X${config_Post_AtlasIPSL} = X ] ) ; then
168    config_Post_AtlasIPSL=FALSE
169  fi
170
171  #====================================================
172  # ParserXIOS : apply default value if not defined
173  if ( [ X${config_Post_ParserXIOS} = X${NULL_STR} ] || [ X${config_Post_ParserXIOS} = X ] ) ; then
174    config_Post_ParserXIOS=FALSE
175  fi
176
177  #====================================================
178  # MetricsPCMDI : apply default value if not defined
179  if ( [ X${config_Post_MetricsPCMDI} = X${NULL_STR} ] || [ X${config_Post_MetricsPCMDI} = X ] ) ; then
180    config_Post_MetricsPCMDI=FALSE
181  fi
182
183  #====================================================
184  # IgnoreNonMonotonic : apply default value if not defined
185  if ( [ X${config_Post_IgnoreNonMonotonic} = X${NULL_STR} ] || [ X${config_Post_IgnoreNonMonotonic} = X ] ) ; then
186    config_Post_IgnoreNonMonotonic=FALSE
187  fi
188
189  #====================================================
190  # LightRestartPack : apply default value if not defined
191  if ( [ X${config_Post_LightRestartPack} = X${NULL_STR} ] || [ X${config_Post_LightRestartPack} = X ] ) ; then
192    config_Post_LightRestartPack=FALSE
193  fi
194
195  #====================================================
196  # Define StackFileLocation : directory where we store stack files
197  # Define StackFileName : stack file containing call tree and instrumentation
198  # Stack file containing call tree will be stored there.
199  if ( $DEBUG_debug ) ; then
200    StackFileLocation=${StackFileLocation:=${R_BUF_KSH}}
201    [ ! -d ${StackFileLocation} ] && mkdir -p ${StackFileLocation}
202    if [ X${TaskType} = Xcomputing ]; then
203      StackFileName=computing.stack.$$
204    elif [ X${TaskType} = Xpost-processing ]; then
205      StackFileName=${Script_Post_Output}.stack.$$
206    elif [ X${TaskType} = Xchecking ]; then
207      StackFileName=checking.stack.$$
208    else
209      IGCM_debug_Exit "IGCM_config_CommonConfiguration unknown TaskType : ${TaskType}"
210      IGCM_debug_Verif_Exit
211    fi
212
213    # This boolean will trigger the filling of the stack
214    # Only now we know where things should be ...
215    # We don't fill the stack when we perform checking task
216    if [ ! X${TaskType} = Xchecking ] ; then
217      ActivateStackFilling=true
218    fi
219  fi
220
221  IGCM_debug_PopStack "IGCM_config_CommonConfiguration"
222}
223
224#===================================
225function IGCM_config_Initialize
226{
227  IGCM_debug_PushStack "IGCM_config_Initialize"
228
229  # Debug Print :
230  echo
231  IGCM_debug_Print 1 "IGCM_config_Initialize"
232
233  # Test modipsl tree existence.
234  IGCM_sys_TestDir ${MODIPSL}
235  [ $? != 0 ] && IGCM_debug_Exit "IGCM_sys_TestDir"
236  IGCM_sys_TestDir ${libIGCM}
237  [ $? != 0 ] && IGCM_debug_Exit "IGCM_sys_TestDir"
238  IGCM_sys_TestDir ${R_EXE}
239  [ $? != 0 ] && IGCM_debug_Exit "IGCM_sys_TestDir"
240  IGCM_sys_TestDir ${SUBMIT_DIR}
241  [ $? != 0 ] && IGCM_debug_Exit "IGCM_sys_TestDir"
242
243  if ( $DEBUG_debug ) ; then
244    echo "Keep trace of inital SUBMIT_DIR : "
245    ls -lta ${SUBMIT_DIR}
246  fi
247
248  #==================================
249  # Read ListOfComponents section:
250  echo
251  IGCM_debug_Print 1 "DefineArrayFromSection : ListOfComponents"
252
253  IGCM_card_DefineArrayFromSection ${SUBMIT_DIR}/config.card ListOfComponents
254  for comp in ${config_ListOfComponents[*]} ; do
255    IGCM_card_DefineArrayFromOption ${SUBMIT_DIR}/config.card ListOfComponents ${comp}
256  done
257  IGCM_debug_Print 3 ${config_ListOfComponents[*]}
258
259  #==================================
260  # Read Executable section:
261  IGCM_card_DefineArrayFromSection   ${SUBMIT_DIR}/config.card Executable
262
263  #==================================
264  # Read Restarts section:
265  # Restarts : Gerneral rule or local for each component.
266  echo
267  IGCM_debug_Print 1 "DefineArrayFromOption : config_Restarts"
268
269  IGCM_card_DefineArrayFromSection ${SUBMIT_DIR}/config.card Restarts
270  for option in ${config_Restarts[*]} ; do
271    IGCM_card_DefineVariableFromOption ${SUBMIT_DIR}/config.card Restarts ${option}
272    eval auxprint=\${config_Restarts_${option}}
273    IGCM_debug_Print 3 "${option} : ${auxprint}"
274  done
275
276  #==================================
277  # Define Job Outputs Name
278  echo
279  IGCM_debug_Print 2 "Define Script_Output_Prefix and Exe_Output"
280  Script_Output_Prefix=${config_UserChoices_Script_Output_Prefix:='Script_Output'}
281  IGCM_debug_Print 3 "Script_Output_Prefix = ${Script_Output_Prefix}"
282  Exe_Output=out_execution
283  IGCM_debug_Print 3 "Exe_Output           = ${Exe_Output}"
284
285  #===================================================================#
286  # Prepare variables available for ${COMP}.card and ${COMP}.driver   #
287  #             But available to any son functions                    #
288  #===================================================================#
289
290  # Convert yyyy-mm-dd date to gregorian yyyymmdd
291  DateBegin=$( IGCM_date_ConvertFormatToGregorian ${config_UserChoices_DateBegin} )
292  DateEnd=$(   IGCM_date_ConvertFormatToGregorian ${config_UserChoices_DateEnd}   )
293
294  # Period Length In Days between DateBegin and DateEnd
295  (( ExperienceLengthInDays=$( IGCM_date_DaysBetweenGregorianDate ${DateEnd} ${DateBegin} )  + 1 ))
296  if [ ${ExperienceLengthInDays} -lt 0 ] ; then
297    IGCM_debug_Print 1 "Problem with dates in config.card : ${DateEnd} < ${DateBegin} ! You must check that."
298    IGCM_debug_Exit "IGCM_config_Initialize" " Wrong Dates."
299    IGCM_debug_Verif_Exit
300  fi
301
302  # Day and Year of Initial State (Given in julian format)
303  InitDay=$(( $( IGCM_date_ConvertGregorianDateToJulian $DateBegin ) % 1000 ))
304  InitYear=$(( $( IGCM_date_ConvertGregorianDateToJulian $DateBegin ) / 1000 ))
305
306  #================================================================#
307  #                  Test and Prepare directories                  #
308  #================================================================#
309
310  # ==> 4 kinds of input files :
311  #     1) R_INIT  : Initial State Files   (Etat0, carteveg)
312  #     2) R_BC    : Boundary Conditions   (Forcages, lai)
313  #     3) Parameters files (allready define through ${SUBMIT_DIR})
314  #     4) Restarts files   (allready define in IGCM_config_Initialize)
315
316  # Here we offer the possibility to redefine R_INIT, R_BC
317  # and PeriodNb through config.card
318  R_INIT=${config_UserChoices_R_INIT:=${R_IN}/INIT}
319  echo
320  IGCM_debug_Print 2 "(Re)Define R_INIT, R_BC and PeriodNb"
321  IGCM_debug_Print 3 "R_IN=${R_IN}"
322  IGCM_debug_Print 3 "R_INIT=${R_INIT}"
323  R_BC=${config_UserChoices_R_BC:=${R_IN}/BC}
324  IGCM_debug_Print 3  "R_BC=${R_BC}"
325  PeriodNb=${config_UserChoices_PeriodNb:=${PeriodNb}}
326  IGCM_debug_Print 3  "Loop in main Job with ${PeriodNb} period(s)"
327
328  # SD ADA SPECIFIC #
329  #      TO FIX     #
330  #IGCM_sys_TestDirArchive ${R_IN}
331  #[ $? != 0 ] && IGCM_debug_Exit "IGCM_sys_TestDirArchive"
332
333  if ( ${FirstInitialize} ) ; then
334    IGCM_sys_MkdirArchive   ${R_SAVE}
335    [ ! ${config_Post_PackFrequency} = NONE ] && IGCM_sys_Mkdir ${R_BUFR}
336  else
337    IGCM_sys_TestDirArchive ${R_SAVE}
338    [ $? != 0 ] && IGCM_debug_Exit "IGCM_sys_TestDirArchive ${R_SAVE}"
339
340    if [ ! ${config_Post_PackFrequency} = NONE ] ; then
341      IGCM_sys_TestDir ${R_BUFR}
342      [ $? != 0 ] && IGCM_debug_Exit "IGCM_sys_TestDir ${R_BUFR}"
343    fi
344
345    # Test state of run in run.card. Will schedule an exit if another process setted it to "Fatal"
346    IGCM_config_StateCheck
347
348    # And EXIT if not OK
349    IGCM_debug_Verif_Exit
350  fi
351
352  #====================================================
353  # Experience type : DEB(ug), DEV(elopment), RUN
354  if [ X${JobType} != XRUN ] ; then
355    echo
356    echo "===================================================="
357    echo "libIGCM JOB is NOT in RUN type mode."
358    echo "!! OUTPUT files will NOT be PROTECTED !!"
359    echo "Be carefull : you can ERASE the result of this job !"
360
361    case ${JobType} in
362    DEB)
363      echo "DEBUG mode : activation of 'set -vx' mode."
364      echo "DEBUG mode : no protection for output files."
365      echo "DEBUG mode : if active force asynchronous rebuild frequency to PeriodLength frequency."
366      ;;
367    DEV)
368      echo "DEVelopment mode : no protection for output files."
369      echo "DEVelopment mode : if active force asynchronous rebuild frequency to PeriodLength frequency."
370      ;;
371    esac
372
373    if ( [ X${config_Post_RebuildFrequency} != XNONE ] && [ ${DRYRUN} -eq 0 ] ) ; then
374      if [ X${config_Post_RebuildFrequency} != X${config_UserChoices_PeriodLength} ] ; then
375        echo "------------"
376        echo "WARNING : Job is NOT in RUN mode then we will force REBUILD Frequency"
377        echo "          to PeriodLength : ${config_UserChoices_PeriodLength}"
378        echo "------------"
379        config_Post_RebuildFrequency=${config_UserChoices_PeriodLength}
380      fi
381    fi
382    echo "===================================================="
383    echo
384  fi
385
386  IGCM_debug_PopStack "IGCM_config_Initialize"
387}
388
389#===================================
390function IGCM_config_DaysInPeriodLength
391{
392  IGCM_debug_PushStack "IGCM_config_DaysInPeriodLength"
393
394  typeset i
395
396  # Determine number of day(s) in PeriodLength :
397  case ${config_UserChoices_PeriodLength} in
398  *Y|*y)
399    PeriodLengthInYears=$( echo ${config_UserChoices_PeriodLength} | sed -e 's/[yY]//' )
400    echo
401    IGCM_debug_Print 2 "Number of years for PeriodLength : ${PeriodLengthInYears}"
402    PeriodLengthInDays=0
403    i=0
404    until [ $i -ge $PeriodLengthInYears ] ; do
405      (( PeriodLengthInDays = PeriodLengthInDays + $( IGCM_date_DaysInYear $(( year + i )) ) ))
406      (( i=i+1 ))
407    done
408    ;;
409  *M|*m)
410    PeriodLengthInMonths=$( echo ${config_UserChoices_PeriodLength} | sed -e 's/[mM]//' )
411    echo
412    IGCM_debug_Print 2 "Number of months for PeriodLength : ${PeriodLengthInMonths}"
413    PeriodLengthInDays=0
414    i=0
415    until [ $i -ge $PeriodLengthInMonths ] ; do
416      if [ $(( 10#${month} + ${i} )) -lt 13 ] ; then
417        (( PeriodLengthInDays  = PeriodLengthInDays + $( IGCM_date_DaysInMonth $year $(( 10#${month} + ${i} )) ) ))
418      else
419        (( PeriodLengthInDays  = PeriodLengthInDays + $( IGCM_date_DaysInMonth $year $(( 10#${month} + ${i} - 12 )) ) ))
420      fi
421      (( i=i+1 ))
422    done
423    ;;
424  *D|*d)
425    PeriodLengthInMonths=0
426    PeriodLengthInDays=$( echo ${config_UserChoices_PeriodLength} | sed -e 's/[dD]//' )
427    echo
428    IGCM_debug_Print 2 "Number of days for PeriodLength : ${PeriodLengthInDays}";;
429  *)
430    IGCM_debug_Exit "IGCM_config_DaysInPeriodLength " ${config_UserChoices_PeriodLength} " invalid period length : choose in *Y, *M, *D."
431    IGCM_debug_Verif_Exit ;;
432  esac
433
434  IGCM_debug_PopStack "IGCM_config_DaysInPeriodLength"
435}
436
437#===================================
438function IGCM_config_DateCoherency
439{
440  IGCM_debug_PushStack "IGCM_config_DateCoherency"
441
442  echo
443  IGCM_debug_Print 1 "IGCM_config_DateCoherency"
444  echo
445
446  typeset Length VerifiedPeriodDateBegin VerifiedPeriodDateEnd
447
448  # check coherency between (PeriodDateBegin, PeriodDateEnd) and (DateBegin, CumulPeriod, PeriodLength)
449  # DateBegin + CumulPeriod*PeriodLength = PeriodDateBegin
450  echo
451
452  case ${config_UserChoices_PeriodLength} in
453  *Y|*y)
454    Length=$( IGCM_date_DaysInCurrentPeriod ${DateBegin} $(( ${CumulPeriod} * ${PeriodLengthInYears} ))Y )
455    ;;
456  *M|*m)
457    Length=$( IGCM_date_DaysInCurrentPeriod ${DateBegin} $(( ${CumulPeriod} * ${PeriodLengthInMonths} ))M )
458    ;;
459  *D|*d)
460    Length=$( IGCM_date_DaysInCurrentPeriod ${DateBegin} $(( ${CumulPeriod} * ${PeriodLengthInDays} ))D )
461    ;;
462  esac
463  VerifiedPeriodDateEnd=$( IGCM_date_AddDaysToGregorianDate ${DateBegin} ${Length}-1 )
464
465  if [ ${VerifiedPeriodDateEnd} != ${PeriodDateEnd} ] ; then
466    IGCM_debug_Print 1 "From run.card PeriodDateEnd is not consistent with DateBegin and CumulPeriod."
467    IGCM_debug_Print 1 "We have DateBegin = ${DateBegin}"
468    IGCM_debug_Print 1 "We have CumulPeriod = ${CumulPeriod}"
469    IGCM_debug_Print 1 "We have PeriodDateEnd = ${PeriodDateEnd}"
470    IGCM_debug_Print 1 "We have VerifiedPeriodDateEnd = ${VerifiedPeriodDateEnd}"
471    IGCM_debug_Print 1 "You must have change run.card in an inconsistent way."
472
473    IGCM_debug_Exit "STOP here to avoid further issues."
474  fi
475
476  # PeriodDateBegin + PeriodLength = PeriodDateEnd
477  VerifiedPeriodDateBegin=$( IGCM_date_AddDaysToGregorianDate ${VerifiedPeriodDateEnd} $(( ${PeriodLengthInDays} * -1 )) )
478
479  IGCM_debug_PopStack "IGCM_config_DateCoherency"
480}
481
482#===================================
483function IGCM_config_StateCheck
484{
485  IGCM_debug_PushStack "IGCM_config_StateCheck"
486
487    #Test state of run in run.card
488    IGCM_card_DefineVariableFromOption ${SUBMIT_DIR}/run.card Configuration PeriodState
489
490    if [ ${run_Configuration_PeriodState} = "Fatal" ] ; then
491      echo
492      IGCM_debug_Print 1 "!! Error in run.card with PeriodState : " ${run_Configuration_PeriodState} "!!"
493      IGCM_debug_Print 1 "Check the overall status of your simulation by visiting this page:"
494      IGCM_debug_Print 1 "https://hermes.ipsl.upmc.fr/static/simulation.detail.html?uid=${simuid}"
495      IGCM_debug_Print 1 "Then try running ${libIGCM}/clean_PeriodLenght.job to clean latest failed period"
496      IGCM_debug_Print 1 "Or try running ${libIGCM}/clean_latestPackperiod.job to clean lastest pack period."
497      IGCM_debug_Print 1 "Or use ${libIGCM}/purge_simulation.job to delete the full simulation."
498      IGCM_debug_Exit
499    elif [ $( echo ${run_Configuration_PeriodState} | grep Fatal | wc -l ) -eq 1 ] ; then
500      echo
501      IGCM_debug_Print 1 "!! Error in run.card with PeriodState : " ${run_Configuration_PeriodState} "!!"
502      IGCM_debug_Print 1 "Compute jobs has been stop because at least the above mentionned post-processing jobs fails."
503      IGCM_debug_Print 1 "Check post-processing jobs carefully by visiting this page:"
504      IGCM_debug_Print 1 "https://hermes.ipsl.upmc.fr/static/simulation.detail.html?uid=${simuid}"
505      IGCM_debug_Print 1 "Please visit that page to see how to fix issues:"
506      IGCM_debug_Print 1 "https://forge.ipsl.jussieu.fr/igcmg_doc/wiki/DocGmonitor"
507      IGCM_debug_Print 1 "Then try running ${libIGCM}/clean_PeriodLenght.job to clean latest failed period"
508      IGCM_debug_Print 1 "Or try running ${libIGCM}/clean_latestPackperiod.job to clean latest pack period."
509      IGCM_debug_Print 1 "Or use ${libIGCM}/purge_simulation.job to delete the full simulation."
510      IGCM_debug_Exit
511    fi
512
513  IGCM_debug_PopStack "IGCM_config_StateCheck"
514}
515
516#===================================
517function IGCM_config_Check
518{
519  IGCM_debug_PushStack "IGCM_config_Check"
520
521  # If one of the following modulo is not zero :
522  # we will issue an error then explain and exit in
523  # AA_job IGCM_debug_Verif_Exit call before binary submission
524
525  echo
526  IGCM_debug_Print 1 "IGCM_config_Check"
527  echo
528
529  typeset i
530
531  # Check RebuildFrequency against key frequencies : PeriodLength ; PackFrequency ; TimeSeriesFrequency ; SeasonalFrequency
532  if ( [ ! X${config_Post_RebuildFrequency} = X${NULL_STR} ] && [ ! X${config_Post_RebuildFrequency} = XNONE ] ) ; then
533    AsynchronousRebuild=true
534    IGCM_debug_Print 1 "Asynchronous rebuild has been activated."
535    echo
536    # modulo (RebuildFrequency and PeriodLength/TimeSeriesFrequency/SeasonalFrequency) must be zero
537    IGCM_debug_Print 1 "Check coherence between RebuildFrequency and PeriodLength"
538    IGCM_post_CheckModuloFrequency config_Post_RebuildFrequency config_UserChoices_PeriodLength
539    IGCM_debug_Print 1 "Check coherence between PackFrequency and RebuildFrequency"
540    IGCM_post_CheckModuloFrequency config_Post_PackFrequency config_Post_RebuildFrequency
541    IGCM_debug_Print 1 "Check coherence between TimeSeriesFrequency and RebuildFrequency"
542    IGCM_post_CheckModuloFrequency config_Post_TimeSeriesFrequency config_Post_RebuildFrequency
543    IGCM_debug_Print 1 "Check coherence between SeasonalFrequency and RebuildFrequency"
544    IGCM_post_CheckModuloFrequency config_Post_SeasonalFrequency config_Post_RebuildFrequency
545  else
546    AsynchronousRebuild=false
547    IGCM_debug_Print 1 "Asynchronous rebuild has not been activated"
548    IGCM_debug_Print 1 "Proceed with standard post-treatment pathway"
549    echo
550    #modulo (PeriodLength and TimeSeriesFrequency/SeasonalFrequency) must be zero
551    IGCM_debug_Print 1 "Check coherence between TimeSeriesFrequency and PeriodLength"
552    IGCM_post_CheckModuloFrequency config_Post_TimeSeriesFrequency config_UserChoices_PeriodLength
553    IGCM_debug_Print 1 "Check coherence between SeasonalFrequency and PeriodLength"
554    IGCM_post_CheckModuloFrequency config_Post_SeasonalFrequency   config_UserChoices_PeriodLength
555  fi
556
557  # Check PackFrequency against other key frequencies
558  # Modulo (PackFrequency and TimeSeriesFrequency/SeasonalFrequency and PeriodLenght) must be zero
559  if ( [ ! X${config_Post_PackFrequency} = X${NULL_STR} ] && [ ! X${config_Post_PackFrequency} = XNONE ] ) ; then
560    Pack=true
561    #
562    IGCM_debug_Print 1 "Check coherence between PackFrequency and PeriodLength"
563    IGCM_post_CheckModuloFrequency config_Post_PackFrequency config_UserChoices_PeriodLength
564    IGCM_debug_Print 1 "Check coherence between TimeSeriesFrequency and PackFrequency"
565    IGCM_post_CheckModuloFrequency config_Post_TimeSeriesFrequency config_Post_PackFrequency
566    IGCM_debug_Print 1 "Check coherence between SeasonalFrequency and PackFrequency"
567    IGCM_post_CheckModuloFrequency config_Post_SeasonalFrequency config_Post_PackFrequency
568  else
569    Pack=false
570  fi
571
572  # modulo (TimeSeriesFrequency and all Chunck2D) must be zero
573  NbJob=${#CHUNCK2D_SIZE[@]}
574  i=0
575  until [ $i -ge $NbJob ]; do
576    value=${CHUNCK2D_SIZE[${i}]}
577    IGCM_debug_Print 1 "Check coherence between ${CHUNCK2D_NAME[${i}]} Chunck2D frequency and TimeSeriesFrequency"
578    IGCM_post_CheckModuloFrequency value config_Post_TimeSeriesFrequency
579    case ${value} in
580    *Y|*y) ;;
581    *)
582      IGCM_debug_Print 1 "All ChunckJob2D frequency must be expressed in year *Y|*y in comp.card"
583      IGCM_debug_Exit "This will stop the job" ;;
584    esac
585    (( i=i+1 ))
586  done
587
588  # modulo (TimeSeriesFrequency and all Chunck3D) must be zero
589  NbJob=${#CHUNCK3D_SIZE[@]}
590  i=0
591  until [ $i -ge $NbJob ]; do
592    value=${CHUNCK3D_SIZE[${i}]}
593    IGCM_debug_Print 1 "Check coherence between ${CHUNCK3D_NAME[${i}]} Chunck3D frequency and TimeSeriesFrequency"
594    IGCM_post_CheckModuloFrequency value config_Post_TimeSeriesFrequency
595    case ${value} in
596    *Y|*y) ;;
597    *)
598      IGCM_debug_Print 1 "All ChunckJob3D frequency must be expressed in year *Y|*y in comp.card"
599      IGCM_debug_Exit "This will stop the job" ;;
600    esac
601    (( i=i+1 ))
602  done
603
604  # check to be sure there is enough space on temporary filesystems to run
605  echo
606  IGCM_debug_Print 1 "Check if there is enough space on temporary filesystem"
607  IGCM_sys_check_quota
608
609  # check to be sure that RUN_DIR_PATH, that will be removed is not pointing to an important directory
610  echo
611  IGCM_debug_Print 1 "Check where RUN_DIR_PATH variable is pointing to"
612  IGCM_sys_check_path
613
614
615  IGCM_debug_PopStack "IGCM_config_Check"
616}
617
618#===================================
619function IGCM_config_ConfigureExecution
620{
621  IGCM_debug_PushStack " IGCM_config_ConfigureExecution"
622
623  #echo
624  IGCM_debug_Print 1 " IGCM_config_ConfigureExecution"
625  #echo
626
627  typeset ExeNameIn ExeNameFirst CompNameFirst configCardPath comp i
628  typeset tempvar tempvarMPI tempvarNOD NbElts NbExec
629
630  # config.card path
631  configCardPath=$1
632
633  coreNumber=0
634  mpiTasks=0
635  openMPthreads=0
636  NbExec=0
637
638  OK_PARA_MPI=false
639  OK_PARA_OMP=false
640  OK_PARA_NOD=false
641  OK_PARA_MPMD=false
642
643  for comp in ${config_ListOfComponents[*]} ; do
644
645    # Manage component executable
646    IGCM_card_DefineArrayFromOption ${configCardPath} Executable ${comp}
647
648    eval ExeNameIn=\${config_Executable_${comp}[0]}
649
650    # NO order in config.card for parallelized values !
651    # just use suffix : MPI , OMP and NOD (for number of NODes.)
652
653    # NOD is the number of NODes allocated
654    eval ${comp}_PROC_NOD=0
655
656    # MPI is the number of MPI processus per nodes
657    eval ${comp}_PROC_MPI=0
658
659    # OMP is the number of OpenMP threads per MPI processus
660    eval ${comp}_PROC_OMP=0
661
662    # Only if we really have an executable for the component :
663    if ( [ "X${ExeNameIn}" != X\"\" ] && [ "X${ExeNameIn}" != "Xinca.dat" ] ) ; then
664
665      IGCM_debug_Print 1 ${comp}
666
667      # Keep the first executable found and the first CompName
668      eval ExeNameFirst=${ExeNameIn}
669      CompNameFirst=${comp}
670
671      # Are we a second executable?
672      (( NbExec = NbExec + 1 ))
673
674      # set 1 MPI task, 1 OpenMP thread and 1 node as default
675      eval ${comp}_PROC_MPI=1
676      eval ${comp}_PROC_OMP=1
677      eval ${comp}_PROC_NOD=1
678
679      eval NbElts=\${#config_Executable_${comp}[@]}
680
681      if [ ${NbElts} -gt 2 ] ; then
682        #
683        # CURRENT METHOD TO SPECIFY MPI AND OMP RESSOURCES
684        #
685        i=2
686        while [ ${i} -lt ${NbElts} ] ; do
687          eval tempvar=\${config_Executable_${comp}[${i}]}
688          IGCM_debug_Print 2 ${tempvar}
689
690          if [ X${tempvar} = X ] ; then
691            IGCM_debug_Print 2 "Error reading MPI/OMP parameters !!!"
692            IGCM_debug_Exit "Check your config.card. Exit now"
693            IGCM_debug_Verif_Exit
694          fi
695
696          case ${tempvar} in
697          *[mM][pP][iI]*)
698            # Read MPI parameter for composante
699            eval ${comp}_PROC_MPI=$( echo ${tempvar} | tr '[a-z]' '[A-Z]' | sed -e "s/MPI//" )
700            OK_PARA_MPI=true;;
701          *[oO][mM][pP]*)
702            # Read OMP parameter for composante
703            eval ${comp}_PROC_OMP=$( echo ${tempvar} | tr '[a-z]' '[A-Z]' | sed -e "s/OMP//" )
704            ;;
705          *[nN][oO][dD]*)
706            # Read NOD (NumBer of Nodes) parameter for composante
707            eval ${comp}_PROC_NOD=$( echo ${tempvar} | tr '[a-z]' '[A-Z]' | sed -e "s/NOD//" )
708            OK_PARA_NOD=true
709            OK_PARA_MPI=true
710            ;;
711          esac
712          (( i = i + 1 ))
713        done
714      else
715        #
716        # BACKWARD COMPATIBILITY NOT SUPPORTED ANYMORE
717        #
718        IGCM_debug_Exit "You are using a deprecated ressources specification mechanism in your config.card"
719        IGCM_debug_Exit "Please check : https://forge.ipsl.jussieu.fr/igcmg_doc/wiki/DocEsetup#ThesectionExecutable"
720        IGCM_debug_Exit "Please modify ${configCardPath}"
721        exit
722      fi
723      if [ ${comp}_PROC_NOD -gt 1 ] ; then
724            if ( [ ${comp}_PROC_MPI -gt 1 ] && [ ${comp}_PROC_OMP -gt 1 ] ) ; then
725              IGCM_debug_Print 2 "Error using MPI/OMP/NOD parameters !!!"
726              IGCM_debug_Exit "It is not allowed to use MPI and OMP and NOD parameters for the same component"
727              IGCM_debug_Exit "Check your config.card. Exit now"
728              IGCM_debug_Verif_Exit
729            fi
730            if [ "${comp}" != "IOS" ] ; then
731              IGCM_debug_Print 2 "Error using NOD parameter !!!"
732              IGCM_debug_Exit "NOD parameter is only available for IOS component "
733              IGCM_debug_Exit "Check your config.card. Exit now"
734              IGCM_debug_Verif_Exit
735            fi
736      fi
737
738      eval tempvarMPI=\${${comp}_PROC_MPI}
739      eval tempvarNOD=\${${comp}_PROC_NOD}
740      eval tempvarOMP=\${${comp}_PROC_OMP}
741
742      # set OMP mode if more than 1 OMP thread.
743      [ ${tempvarOMP} -ge 2 ] && OK_PARA_OMP=true
744
745      # Number of OMP threads
746      [ ${openMPthreads} -lt ${tempvarOMP} ] && openMPthreads=${tempvarOMP}
747
748      # SUM UP NUMBER OF CORES
749      if [ ${comp}_PROC_NOD -gt 1 ] ; then 
750          (( coreNumber = coreNumber + tempvarNOD * NB_CORE_PER_NODE ))
751      else
752          (( coreNumber = coreNumber + tempvarMPI * tempvarNOD * tempvarOMP ))
753      fi
754      # SUM UP NUMBER OF MPI TASKS
755      (( mpiTasks = mpiTasks + tempvarMPI * tempvarNOD ))
756    fi
757  done
758
759  # MANDATORY FOR THE OPA9.DRIVER. USED TO EDIT OPA NAMELIST
760  # WE SHOULD PLANIFY NUM_PROC_??? DEPRECATION
761  NUM_PROC_CPL=${CPL_PROC_MPI}
762  NUM_PROC_OCE=${OCE_PROC_MPI}
763  NUM_PROC_ATM=${ATM_PROC_MPI}
764
765  # set MPMD mode if more than 2 executable names.
766  [ ${NbExec} -ge 2 ] && OK_PARA_MPMD=true 
767
768  # Define the execution type we are running in
769  if ( ${OK_PARA_MPMD} ) ; then
770    if ( ${OK_PARA_MPI} ) ; then
771      # MPMD always implies MPI
772      executionType=1
773    fi
774    if ( ${OK_PARA_OMP} ) ; then
775      # MPMD + MPI/OMP
776      executionType=2
777    fi
778  else
779    if ( ( ${OK_PARA_MPI} ) && ( ${OK_PARA_OMP} ) ) ; then
780      # SPMD + MPI/OMP
781      executionType=3
782    elif ( ( ${OK_PARA_MPI} ) && ( ! ${OK_PARA_OMP} ) ) ; then
783      # SPMD + MPI only
784      executionType=4
785    elif ( ( ! ${OK_PARA_MPI} ) && ( ${OK_PARA_OMP} ) ) ; then
786      # SPMD + OMP only
787      executionType=5
788    elif ( ( ! ${OK_PARA_MPI} ) && ( ! ${OK_PARA_OMP} ) ) ; then
789      # SEQUENTIAL THEN
790      executionType=6
791      coreNumber=1
792    fi
793  fi
794
795  IGCM_debug_Print 1 "MPI/OMP treatment coreNumber = ${coreNumber}"
796  IGCM_debug_Print 1 "MPI/OMP treatment mpiTasks = ${mpiTasks}"
797  IGCM_debug_Print 1 "MPI/OMP treatment openMPthreads = ${openMPthreads}"
798  IGCM_debug_Print 1 "MPI/OMP treatment executionType = ${executionType}"
799
800  IGCM_debug_PopStack "IGCM_config_ConfigureExecution"
801}
802
803#===================================
804function IGCM_config_PeriodStart
805{
806  IGCM_debug_PushStack "IGCM_config_PeriodStart"
807
808  echo
809  IGCM_debug_Print 1 "IGCM_config_PeriodStart"
810  echo
811
812  if ( ${FirstInitialize} ) ; then
813    #================================================#
814    #         Initialize date/period information     #
815    #================================================#
816
817    IGCM_date_GetYearMonthDay ${DateBegin} year month day
818    IGCM_config_DaysInPeriodLength
819
820    PeriodDateBegin=${DateBegin}
821    PeriodDateEnd=$( IGCM_date_AddDaysToGregorianDate ${DateBegin} $(( ${PeriodLengthInDays} - 1 )) )
822    CumulPeriod=1
823
824    #=================================================#
825    #              Write updated run.card             #
826    #=================================================#
827
828    #Correct run.card Configuration for this period
829    IGCM_card_WriteOption ${SUBMIT_DIR}/run.card Configuration PeriodDateBegin ${PeriodDateBegin}
830    IGCM_card_WriteOption ${SUBMIT_DIR}/run.card Configuration PeriodDateEnd ${PeriodDateEnd}
831    IGCM_card_WriteOption ${SUBMIT_DIR}/run.card Configuration CumulPeriod ${CumulPeriod}
832    if [ X$( grep "SubmitPath" ${SUBMIT_DIR}/run.card ) != X ] ; then
833      IGCM_card_WriteOption ${SUBMIT_DIR}/run.card Configuration SubmitPath ${SUBMIT_DIR}
834    fi
835
836    IGCM_card_WriteOption ${SUBMIT_DIR}/run.card Configuration PeriodState "Running"
837
838  else
839    #================================================#
840    #         The file run.card allready exist       #
841    #================================================#
842
843    # Test state of run in run.card. Will schedule an exit if another process setted it to "Fatal"
844    IGCM_config_StateCheck
845    # And EXIT if not OK
846    IGCM_debug_Verif_Exit
847
848    #===================================#
849    #        Read updated run.card      #
850    #===================================#
851
852    IGCM_card_DefineVariableFromOption ${SUBMIT_DIR}/run.card Configuration PeriodDateBegin
853    IGCM_card_DefineVariableFromOption ${SUBMIT_DIR}/run.card Configuration PeriodDateEnd
854    IGCM_card_DefineVariableFromOption ${SUBMIT_DIR}/run.card Configuration CumulPeriod
855
856    PeriodDateBegin=$( IGCM_date_ConvertFormatToGregorian ${run_Configuration_PeriodDateBegin} )
857    PeriodDateEnd=$( IGCM_date_ConvertFormatToGregorian ${run_Configuration_PeriodDateEnd} )
858    CumulPeriod=${run_Configuration_CumulPeriod}
859
860    LastPeriodDateEnd=$( IGCM_date_AddDaysToGregorianDate $( IGCM_date_ConvertFormatToGregorian ${PeriodDateBegin} ) -1 )
861
862    if [ ${Period} = 1 ]; then
863      # save last Job output and current run.card
864      typeset Potential
865      IGCM_sys_Cd ${SUBMIT_DIR}
866      #
867      IGCM_debug_Print 2 "Save previous ksh job output"
868      for Potential in $( ls ${Script_Output_Prefix}_${config_UserChoices_JobName}.[0-9][0-9][0-9][0-9][0-9][0-9] ) ; do
869        if [ X${Pack} = Xtrue ] ; then
870          ( IGCM_sys_TestFileBuffer  ${R_BUF_KSH}/${Potential} ) || IGCM_sys_Cp ${Potential} ${R_BUF_KSH}/${Potential}.$$
871        else
872          ( IGCM_sys_TestFileArchive ${R_OUT_KSH}/${Potential} ) || IGCM_sys_Put_Out ${Potential} ${R_OUT_KSH}/${Potential}.$$ NOMOVE
873          IGCM_debug_Print 1 "Save of previous ksh job output is not done for Pack=false"
874        fi
875      done
876
877      #
878      IGCM_debug_Print 2 "Save current run.card"
879      IGCM_card_CheckConflict run.card
880
881      if [ X${Pack} = Xtrue ] ; then
882        IGCM_sys_Cp ${SUBMIT_DIR}/run.card ${R_BUF_KSH}/run.card
883      else
884        IGCM_sys_Put_Out ${SUBMIT_DIR}/run.card ${R_OUT_KSH}/run.card NOMOVE
885        IGCM_debug_Print 1 "Save of run.card is not done for Pack=false"
886      fi
887      #
888      IGCM_sys_Cd ${RUN_DIR}
889    else
890      unset FileToBeDeleted
891    fi
892
893    # Determine number of day(s) in PeriodLength
894    IGCM_date_GetYearMonthDay $PeriodDateBegin year month day
895    IGCM_config_DaysInPeriodLength
896
897    # Check coherency between (PeriodDateBegin, PeriodDateEnd) and (DateBegin, CumulPeriod, PeriodLength)
898    IGCM_config_DateCoherency
899    # And EXIT if not OK
900    IGCM_debug_Verif_Exit
901
902    # Test state of run in run.card. Will schedule an exit if another process setted it to "Fatal"
903    IGCM_config_StateCheck
904    # And EXIT if not OK
905    IGCM_debug_Verif_Exit
906
907    # We can say we are "Running" now.
908    IGCM_card_WriteOption ${SUBMIT_DIR}/run.card Configuration PeriodState "Running"
909  fi
910
911  # BEGIN: SHOULD GO IN A FUNCTION FROM libIGCM_date.ksh
912  # Compute year_m1 and year_p1 (year minus 1Y and year plus 1Y)
913  year_m1=$(( year - 1 ))
914  year_p1=$(( year + 1 ))
915  # Compute month_m1 (month minus 1M)
916  # Compute yyyymm_m1 (yyyymm minus 1M)
917  month_m1=$(( 10#${month} - 1 ))
918  if [ ${month_m1} = 0 ]; then
919    month_m1=12
920    yyyymm_m1=${year_m1}12
921  elif [ ${month_m1} -le 9 ]; then
922    month_m1=0${month_m1}
923    yyyymm_m1=${year}${month_m1}
924  else
925    yyyymm_m1=${year}${month_m1}
926  fi
927  # Compute month_p1 (month plus 1M)
928  # Compute yyyymm_p1 (yyyymm plus 1M)
929  month_p1=$(( 10#${month} + 1 ))
930  if [ ${month_p1} = 13 ]; then
931    month_p1=01
932    yyyymm_p1=${year_p1}01
933  elif [ ${month_p1} -le 9 ]; then
934    month_p1=0${month_p1}
935    yyyymm_p1=${year}${month_p1}
936  else
937    yyyymm_p1=${year}${month_p1}
938  fi
939
940  #===================================================================#
941  # Calculate CyclicYear to be used for looping over a given forcing  #
942  # period. Add CyclicBegin and CyclicEnd in config.card UserChoices. #
943  #===================================================================#
944
945  # To use the variable CyclicYear, one must add in config.card CyclicBegin and CyclicEnd.
946  # CyclicBegin is the first year in the cycle. CyclicEnd is the last year included in the cycle.
947  if ( [ ! X${config_UserChoices_CyclicBegin} = X ] && [ ! X${config_UserChoices_CyclicEnd} = X ] ) ; then
948    CycleNb=$(( ${config_UserChoices_CyclicEnd} - ${config_UserChoices_CyclicBegin} + 1 ))
949    CyclicYear_p1=NOTDEFINED
950
951    # For current year
952    yeartmp=$year
953    diffy=$(( $yeartmp - ${config_UserChoices_CyclicBegin} ))
954    while [ $diffy -lt 0 ] ; do
955      yeartmp=$(( ${yeartmp} + ${CycleNb} ))
956      diffy=$(( $yeartmp - ${config_UserChoices_CyclicBegin} ))
957    done
958    CyclicYear=$(( ( ${diffy} % ${CycleNb} ) + ${config_UserChoices_CyclicBegin} ))
959
960    # For next coming year
961    yeartmp=$(( $year + 1 ))
962    diffy=$(( $yeartmp - ${config_UserChoices_CyclicBegin} ))
963    while [ $diffy -lt 0 ] ; do
964      yeartmp=$(( ${yeartmp} + ${CycleNb} ))
965      diffy=$(( $yeartmp - ${config_UserChoices_CyclicBegin} ))
966    done
967    CyclicYear_p1=$(( ( ${diffy} % ${CycleNb} ) + ${config_UserChoices_CyclicBegin} ))
968
969    IGCM_debug_Print 1 "CyclicYear   = ${CyclicYear}, CyclicYear_p1 = ${CyclicYear_p1}, current year=$year"
970  else
971    CyclicYear="ERROR_CyclicYear_Variable_Not_Defined"
972    CyclicYear_p1="ERROR_CyclicYear_p1_Variable_Not_Defined"
973    IGCM_debug_Print 1 "CyclicYear wont be use without adding CyclicBegin and CyclicEnd in config.card"
974  fi
975
976  # END: SHOULD GO IN A FUNCTION FROM libIGCM_date.ksh
977
978  #===================================================================#
979  # Prepare variables available for ${COMP}.card and ${COMP}.driver   #
980  #             But available to any son functions                    #
981  #===================================================================#
982
983  # Period Length In Days between DateBegin and DateCurrent (at end of period == PeriodDateEnd !)
984  (( SimulationLengthInDays = $( IGCM_date_DaysBetweenGregorianDate ${PeriodDateEnd} ${DateBegin} ) + 1 ))
985
986  # Debug Print :
987  echo
988  IGCM_debug_Print 1 "IGCM_config_PeriodStart : Before Execution"
989  IGCM_debug_Print 1 "Year of simulation      : ${year}"
990  IGCM_debug_Print 1 "Month of simulation     : ${month}"
991  IGCM_debug_Print 1 "PeriodLengthInDays      : ${PeriodLengthInDays}"
992  IGCM_debug_Print 1 "PeriodDateBegin         : ${PeriodDateBegin}"
993  IGCM_debug_Print 1 "PeriodDateEnd           : ${PeriodDateEnd}"
994  IGCM_debug_Print 1 "SimulationLengthInDays  : ${SimulationLengthInDays}"
995  IGCM_debug_Print 1 "ExperienceLengthInDays  : ${ExperienceLengthInDays}"
996
997  #================================================================#
998  #         Prepare variables available for comp_finalyze          #
999  #================================================================#
1000
1001  # Period for save files
1002  DatesPeriod=${PeriodDateBegin}_${PeriodDateEnd}
1003
1004  # Prefix for save files of this period
1005  PREFIX=${config_UserChoices_JobName}_${DatesPeriod}
1006
1007  # List of files that will be deleted in RUN_DIR after run
1008  [ -f stack ] && FileToBeDeleted[0]="stack"
1009
1010  # Test if the same run as already been saved :
1011  if [ X${JobType} = XRUN ] ; then
1012    if [ ${DRYRUN} -le 0 ] ; then
1013      if ( IGCM_sys_TestFileBuffer ${R_BUF_KSH}/${PREFIX}_${Exe_Output} ) ; then
1014        IGCM_debug_Exit "IGCM_config_PeriodStart" "You are currently re-running an old job."
1015        IGCM_debug_Print 1 "Because of readonly permissions, you can't re-run a job when saved files"
1016        IGCM_debug_Print 1 " are still in the ARCHIVE directory. You must deleted those files, or "
1017        IGCM_debug_Print 1 " the whole ${R_SAVE} tree. See different clean_*.job in ${libIGCM} directory."
1018        IGCM_debug_Print 1 " This exit has been initiated because at least ${R_BUF_KSH}/${PREFIX}_${Exe_Output} exists."
1019        IGCM_debug_Verif_Exit
1020      fi
1021    fi
1022  else
1023    if ( IGCM_sys_TestFileBuffer ${R_BUF_KSH}/${PREFIX}_${Exe_Output} ) ; then
1024      IGCM_debug_Print 1 "IGCM_config_PeriodStart" "RErun an old job. Allowed in DEBUG or DEV mode."
1025    fi
1026  fi
1027
1028  #================================================================#
1029  #       Prepare variables available for binary execution         #
1030  #       Call function for creation of run script                 #
1031  #       Only done once per job                                   #
1032  #================================================================#
1033
1034  if [ ${Period} -eq 1 ]; then
1035    # Define the execution context (MPMD, SPMD, MPI/OMP ...)
1036    IGCM_config_ConfigureExecution ${SUBMIT_DIR}/config.card
1037    # Create the execution script for the current context
1038    IGCM_sys_build_execution_scripts
1039  fi
1040
1041  ExecutionFail=false
1042
1043  # Update the rabbitMQ queue
1044  IGCM_debug_BigBro_Update
1045
1046  IGCM_debug_PopStack "IGCM_config_PeriodStart"
1047}
1048
1049#===================================
1050function IGCM_config_SaveSourceModifications
1051{
1052  IGCM_debug_PushStack "IGCM_config_SaveSourceModifications"
1053
1054  typeset ExeOutDateMax listVarEnv
1055  ExeOutDateMax=$1
1056
1057  listVarEnv="ExeOutDateMax,R_OUT_EXE,PREFIX,SUBMIT_DIR"
1058  IGCM_sys_RshMaster "\
1059    . ${libIGCM}/libIGCM_sys/libIGCM_sys.ksh; \
1060    export ExeOutDateMax=${ExeOutDateMax};\
1061    export R_OUT_EXE=${R_OUT_EXE};\
1062    export PREFIX=${PREFIX};\
1063    export SUBMIT_DIR=${SUBMIT_DIR};\
1064    export listVarEnv=${listVarEnv};\
1065    Script_Output=out_SaveSourceModifications;\
1066    IGCM_sys_Qsub ${libIGCM}/SaveSourceModifications.job ${ExeOutDateMax} ${R_OUT_EXE} ${PREFIX} ${SUBMIT_DIR}"
1067
1068  IGCM_debug_PopStack "IGCM_config_SaveSourceModifications"
1069}
1070
1071#===================================
1072function IGCM_config_PeriodEnd
1073{
1074  IGCM_debug_PushStack "IGCM_config_PeriodEnd"
1075
1076  echo
1077  IGCM_debug_Print 1 "IGCM_config_PeriodEnd"
1078  echo
1079
1080  if [ ${DRYRUN} -le 1 ] ; then
1081
1082    IGCM_debug_Print 1 "Check components binary : size and creation date"
1083
1084    typeset LS_comp LS_bin ExeDate ExeCpuLog NextExeSize LastCompExeSize
1085    typeset comp i
1086    typeset ExeNameIn ExeNameOut UpdateExe ExeSecDateMax
1087
1088    #==================================#
1089    #        Get last Exe Size         #
1090    #==================================#
1091
1092    (( i=0 ))
1093    if ( ${FirstInitialize} ) ; then
1094      run_Log_LastExeSize=""
1095      for comp in ${config_ListOfComponents[*]} ; do
1096        run_Log_LastExeSize[$i]=0
1097        (( i=i+1 ))
1098      done
1099    else
1100      IGCM_card_DefineArrayFromOption ${SUBMIT_DIR}/run.card Log LastExeSize
1101    fi
1102    #==================================#
1103    #         And Build ExeDate        #
1104    #==================================#
1105
1106    # 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
1107    # 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")
1108    # 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
1109    ExeDate=""
1110    NextExeSize="( "
1111    (( i=0 ))
1112    UpdateExe=false
1113    (( ExeSecDateMax = 0 ))
1114    for comp in ${config_ListOfComponents[*]} ; do
1115
1116      IGCM_debug_Print 3 ${comp}
1117
1118      eval ExeNameIn=\${config_Executable_${comp}[0]}
1119      eval ExeNameOut=\${config_Executable_${comp}[1]}
1120      # Only if we really have an executable for the component :
1121      if [ X${ExeNameIn} = X\"\" ] ; then
1122        # If there is no exe file for this component
1123        (( ExeSize=0 ))
1124      else
1125        eval ExeNameIn=${ExeNameIn}
1126        LS_bin=${R_EXE}/${ExeNameIn}
1127        IGCM_sys_FileSize ${LS_bin} ExeSize
1128
1129        set +A LS_comp -- $( LC_TIME=en_US ls -l ${LS_bin} )
1130        if [ X${ExeDate} = X ] ; then
1131          # First component exe date
1132          ExeDate=${comp}_${LS_comp[5]}_${LS_comp[6]}
1133        else
1134          ExeDate=${ExeDate}-${comp}_${LS_comp[5]}_${LS_comp[6]}
1135        fi
1136        ExeDate=${ExeDate}_${LS_comp[7]}
1137      fi
1138
1139      if [ ${i} -eq 0 ] ; then
1140        # First component
1141        NextExeSize="( "${ExeSize}
1142      else
1143        NextExeSize=${NextExeSize}", "${ExeSize}
1144      fi
1145      LastCompExeSize=${run_Log_LastExeSize[$i]}
1146      (( i=i+1 ))
1147
1148      if [ ${ExeSize} -ne ${LastCompExeSize} ] ; then
1149        if ( ${FirstInitialize} ) ; then
1150          IGCM_debug_Print 1 "Save first ${ExeNameIn} in ${R_OUT_EXE} !"
1151        else
1152          IGCM_debug_Print 1 "${ExeNameIn} has changed in ${R_EXE} !"
1153          IGCM_debug_Print 1 "Save latest ${ExeNameIn} in ${R_OUT_EXE} !"
1154          FileToBeDeleted[${#FileToBeDeleted[@]}]=${ExeNameOut}
1155        fi
1156        IGCM_sys_Put_Out ${ExeNameOut} ${R_OUT_EXE}/${PREFIX}_${ExeNameIn} rw
1157        UpdateExe=true
1158
1159        # SD : switch off for now
1160        #IGCM_sys_GetDate_FichWork ${LS_bin} ExeSecDate
1161        #if [ $ExeSecDateMax -lt $ExeSecDate ] ; then
1162        #  ExeSecDateMax=$ExeSecDate
1163        #fi
1164      fi
1165    done
1166
1167    # SD : switch off for now
1168    #if ( ${UpdateExe} ) ; then
1169    #  echo "Launch SaveSourceModifications."
1170    #  IGCM_config_SaveSourceModifications ${ExeSecDateMax}
1171    #fi
1172
1173    NextExeSize=${NextExeSize}" )"
1174    IGCM_card_WriteOption ${SUBMIT_DIR}/run.card Log LastExeSize "${NextExeSize}"
1175
1176    if [ ${DRYRUN} -le 1 ] ; then
1177      tail -1500 ${Exe_Output} > ${Exe_Output}_tail.txt
1178      ExeCpuLog=$( gawk -f ${libIGCM}/libIGCM_sys/IGCM_add_out.awk ${Exe_Output}_tail.txt )
1179      RET=$?
1180      if [ $RET -eq 0 ] ; then
1181        # ExeCpuLog variable contents 5 fields
1182        echo "${CumulPeriod} ${PeriodDateBegin} ${PeriodDateEnd} ${ExeCpuLog} ${ExeDate}" |   \
1183          gawk '{printf("# %11d | %15s | %15s | %19s | %19s | %15.5f | %15.5f | %15.5f | %s\n", \
1184            $1,$2,$3,$4,$5,$6,$7,$8,$9)}' >> ${SUBMIT_DIR}/run.card
1185      fi
1186      FileToBeDeleted[${#FileToBeDeleted[@]}]=${Exe_Output}_tail.txt
1187    fi
1188
1189  fi
1190
1191  #==================================#
1192  #         Save Job output          #
1193  #==================================#
1194  if [ X${Pack} = Xtrue ] ; then
1195    IGCM_sys_PutBuffer_Out ${Exe_Output} ${R_BUF_KSH}/${PREFIX}_${Exe_Output}
1196  else
1197    IGCM_sys_Put_Out ${Exe_Output} ${R_OUT_KSH}/${PREFIX}_${Exe_Output}
1198  fi
1199  FileToBeDeleted[${#FileToBeDeleted[@]}]=${Exe_Output}
1200
1201  # All was right ? no ? then we stop.
1202  IGCM_debug_Verif_Exit
1203
1204  # If all was OK, we can delete all files not necessary for next Job
1205  echo
1206  IGCM_debug_Print 1 "Files that will be deleted before next period-run : "
1207
1208  if [ ${DRYRUN} -le 2 ] ; then
1209    for f in ${FileToBeDeleted[@]} ; do [ -f ${f} ] && ls -la $f ; [ -f ${f} ] && rm -f $f ; done
1210  else
1211    echo ${FileToBeDeleted[@]}
1212  fi
1213
1214  # Send some accounting element to the user if CumulPeriod=3
1215  if [ ${CumulPeriod} -eq 3 ] ; then
1216    echo
1217    IGCM_debug_Print 1 "Send email containing some accounting information : "
1218
1219    RealCpuTime=$( echo ${ExeCpuLog} | gawk '{print $3}' )
1220
1221    consumeHoursPerPeriod=$( echo "scale=6;${RealCpuTime}*${coreNumber}/3600" | bc )
1222
1223    consumeHoursPerWholeSimulation=$( echo "scale=6;${consumeHoursPerPeriod}/${PeriodLengthInDays}*${ExperienceLengthInDays}" | bc )
1224
1225    recommendedPeriodNb=$( echo "scale=6;${jobWarningDelay}/3600/${consumeHoursPerPeriod}*${coreNumber}" | bc )
1226
1227    IGCM_sys_SendMail Accounting
1228  fi
1229
1230  #=================================================#
1231  #         Modification of libIGCM behaviour       #
1232  #=================================================#
1233
1234  # To use this function, one must copy libIGCM.card from ${libIGCM} directory
1235  # and put it in ${SUBMIT_DIR} directory. After modifications of ${SUBMIT_DIR}/libIGCM.card,
1236  # variables define inside [UserChanges] will be modified for next Period of libIGCM main loop.
1237  if [ -f ${SUBMIT_DIR}/libIGCM.card ] ; then
1238    echo
1239    echo "########################################################################"
1240    echo "!!!                 Modification of libIGCM behaviour                !!!"
1241    echo
1242
1243    IGCM_debug_Print 1 "DefineArrayFromOption  : libIGCM_UserChanges in libIGCM.card"
1244    IGCM_card_DefineArrayFromSection ${SUBMIT_DIR}/libIGCM.card UserChanges
1245    IGCM_debug_Print 2 "libIGCM_UserChanges" ${libIGCM_UserChanges[*]}
1246
1247    # Special treatments for libIGCM internals
1248    for option in ${libIGCM_UserChanges[*]} ; do
1249      IGCM_card_DefineVariableFromOption ${SUBMIT_DIR}/libIGCM.card UserChanges ${option}
1250
1251      echo "We will change : ${option}."
1252      eval echo "Previous value : " \${${option}}
1253      eval echo "Change to : " \${libIGCM_UserChanges_${option}}
1254
1255      eval ${option}=\${libIGCM_UserChanges_${option}}
1256
1257      case ${option} in
1258      config_UserChoices_DateEnd)
1259        IGCM_debug_PrintVariables 1 config_UserChoices_DateEnd
1260        DateEnd=$( IGCM_date_ConvertFormatToGregorian ${config_UserChoices_DateEnd} )
1261
1262        # Period Length In Days between DateBegin and DateEnd
1263        (( ExperienceLengthInDays=$( IGCM_date_DaysBetweenGregorianDate ${DateEnd} ${DateBegin} )  + 1 ))
1264        if [ ${ExperienceLengthInDays} -lt 0 ] ; then
1265          IGCM_debug_Print 1 "Problem with dates in libIGCM.card : ${DateEnd} < ${DateBegin} ! You must check that."
1266          IGCM_debug_Exit "IGCM_PeriodEnd have wrong dates."
1267          IGCM_debug_Verif_Exit
1268        fi
1269        ;;
1270      config_UserChoices_PeriodLength)
1271        IGCM_debug_Print 1  "Change config_UserChoices_PeriodLength=${config_UserChoices_PeriodLength}"
1272        ;;
1273      PeriodNb)
1274        IGCM_debug_Print 1  "Loop in main Job with ${PeriodNb} period(s)"
1275        ;;
1276      config_Post_RebuildFrequency)
1277        IGCM_debug_Print 1  "Change config_Post_RebuildFrequency=${config_Post_RebuildFrequency} : IGCM_post_Configure"
1278        IGCM_post_Configure
1279        ;;
1280      config_Post_TimeSeriesFrequency)
1281        IGCM_debug_Print 1  "Change config_Post_TimeSeriesFrequency = ${config_Post_TimeSeriesFrequency} : IGCM_post_Configure"
1282        IGCM_post_Configure
1283        ;;
1284      config_Post_SeasonalFrequency)
1285        IGCM_debug_Print 1  "Change config_Post_SeasonalFrequency = ${config_Post_SeasonalFrequency} : IGCM_post_Configure"
1286        IGCM_post_Configure
1287        ;;
1288      esac
1289    done
1290
1291    echo
1292    echo "########################################################################"
1293    echo
1294  fi
1295
1296  #=================================================#
1297  #         Determine next computed period          #
1298  #=================================================#
1299
1300  PeriodDateBegin=$( IGCM_date_AddDaysToGregorianDate ${PeriodDateEnd} 1 )
1301  IGCM_date_GetYearMonthDay $PeriodDateBegin year month day
1302  year_m1=$(( year - 1 ))
1303  year_p1=$(( year + 1 ))
1304  IGCM_config_DaysInPeriodLength
1305  PeriodDateEnd=$( IGCM_date_AddDaysToGregorianDate ${PeriodDateBegin} $(( ${PeriodLengthInDays} - 1 )) )
1306
1307  # Debug Print :
1308  echo
1309  IGCM_debug_Print 1 "IGCM_config_PeriodEnd : Preparing Next Execution"
1310  IGCM_debug_Print 1 "PeriodDateBegin       : ${PeriodDateBegin}"
1311  IGCM_debug_Print 1 "PeriodDateEnd         : ${PeriodDateEnd}"
1312  IGCM_debug_Print 1 "PeriodLengthInDays    : ${PeriodLengthInDays}"
1313
1314  PeriodDateBegin=$( IGCM_date_ConvertFormatToHuman ${PeriodDateBegin} )
1315  PeriodDateEnd=$( IGCM_date_ConvertFormatToHuman ${PeriodDateEnd} )
1316
1317  (( CumulPeriod = CumulPeriod + 1 ))
1318
1319  # Debug Print :
1320  echo
1321  IGCM_debug_Print 3 "PeriodDateBegin Human : ${PeriodDateBegin}"
1322  IGCM_debug_Print 3 "PeriodDateEnd Human   : ${PeriodDateEnd}"
1323  IGCM_debug_Print 3 "CumulPeriod           : ${CumulPeriod}"
1324
1325  #=================================================#
1326  #             Write updated run.card              #
1327  #=================================================#
1328
1329  IGCM_card_WriteOption ${SUBMIT_DIR}/run.card Configuration PeriodDateBegin ${PeriodDateBegin}
1330  IGCM_card_WriteOption ${SUBMIT_DIR}/run.card Configuration PeriodDateEnd ${PeriodDateEnd}
1331  IGCM_card_WriteOption ${SUBMIT_DIR}/run.card Configuration CumulPeriod ${CumulPeriod}
1332
1333  if ( ${FirstInitialize} ) ; then
1334    # It's no more the first time
1335    FirstInitialize=false
1336  fi
1337
1338  IGCM_debug_PopStack "IGCM_config_PeriodEnd"
1339}
1340
1341#===================================
1342function IGCM_config_Finalize
1343{
1344  IGCM_debug_PushStack "IGCM_config_Finalize"
1345
1346  echo
1347  IGCM_debug_Print 1 "IGCM_config_Finalize"
1348  echo
1349
1350  # Test state of run in run.card. Will schedule an exit if another process setted it to "Fatal"
1351  IGCM_config_StateCheck
1352
1353  # And EXIT if not OK
1354  IGCM_debug_Verif_Exit
1355
1356  if [ ${SimulationLengthInDays} -ge ${ExperienceLengthInDays} ] ; then
1357    #==========================#
1358    # End of entire simulation #
1359    #==========================#
1360    simulationIsOver=true
1361
1362    # Mail notification
1363    IGCM_sys_SendMail
1364    #
1365    IGCM_card_WriteOption ${SUBMIT_DIR}/run.card Configuration PeriodState "Completed"
1366    #
1367    IGCM_debug_Print 1 "Normal End of computation."
1368
1369  else
1370    #=================#
1371    # Submit next job #
1372    #=================#
1373    simulationIsOver=false
1374
1375    IGCM_card_WriteOption ${SUBMIT_DIR}/run.card Configuration PeriodState "OnQueue"
1376
1377    # Name of next Ksh Script output :
1378    Script_Output=${Script_Output_Prefix}_${config_UserChoices_JobName}.$( printf "%06d" ${CumulPeriod} )
1379
1380    IGCM_debug_Print 1 "Submit next job"
1381    # SUBMIT NEXT JOB from SUBMIT_DIR and come back in RUN_DIR
1382    IGCM_sys_Cd ${SUBMIT_DIR}
1383    # Keep only the 5 latest ${Script_Output_Prefix}_${config_UserChoices_JobName}
1384    ScriptTot=$( ls ${Script_Output_Prefix}_${config_UserChoices_JobName}.?????? 2>/dev/null | wc -l )
1385    [ ${ScriptTot} -gt 5 ] && rm -f $( ls ${Script_Output_Prefix}_${config_UserChoices_JobName}.?????? | head -$(( ${ScriptTot} - 5 )) )
1386    # Submit next job and come back
1387    IGCM_sys_Qsub ${SUBMIT_DIR}/Job_${config_UserChoices_JobName}
1388    IGCM_sys_Cd -
1389  fi
1390
1391  # Clean ${RUN_DIR}=${RUN_DIR_PATH}/${config_UserChoices_JobName}.${$}
1392  # Only for production run (No clean up in DEV or DEB mode)
1393  # and command sent from .. directory.
1394  IGCM_sys_Cd ..
1395  [ X${JobType} = XRUN ] && IGCM_sys_RmRunDir -rf ${RUN_DIR_PATH}
1396
1397  # Inform the rabbitMQ queue
1398  IGCM_debug_BigBro_Finalize
1399
1400  IGCM_debug_PopStack "IGCM_config_Finalize"
1401}
1402
1403#===================================
Note: See TracBrowser for help on using the repository browser.