Merge branch 'master' of github.com:OpenFOAM/OpenFOAM-2.0.x
[OpenFOAM-2.0.x.git] / bin / foamEndJob
blob09f701d1bf313c9b1c46efe1a7a6dc3ae62df698
1 #!/bin/sh
2 #------------------------------------------------------------------------------
3 # ========= |
4 # \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 # \\ / O peration |
6 # \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
7 # \\/ M anipulation |
8 #-------------------------------------------------------------------------------
9 # License
10 # This file is part of OpenFOAM.
12 # OpenFOAM is free software: you can redistribute it and/or modify it
13 # under the terms of the GNU General Public License as published by
14 # the Free Software Foundation, either version 3 of the License, or
15 # (at your option) any later version.
17 # OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
18 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 # for more details.
22 # You should have received a copy of the GNU General Public License
23 # along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25 # Script
26 # foamEndJob
28 # Description
29 # Ends running job on current machine. Called with root,case,pid.
30 # - checks if pid exists
31 # - modifies controlDict
32 # - waits until
33 # - pid disappeared
34 # - controlDict modified
35 # to restore controlDict
37 #-------------------------------------------------------------------------------
38 Script=${0##*/}
40 usage() {
41 exec 1>&2
42 while [ "$#" -ge 1 ]; do echo "$1"; shift; done
43 cat<<USAGE
44 Usage: $Script [OPTION] <pid>
45 Usage: $Script [OPTION] -c
47 options:
48 -clear use blockMesh reader (uses .blockMesh extension)
49 -case <dir> specify alternative case directory, default is the cwd
50 -now stop at next time step
51 -help print the usage
53 Tries to end running OpenFOAM application at next write (or optionally
54 at the next time step). It needs runTimeModifiable switched on in the
55 controlDict. It changes stopAt in the controlDict and waits for the
56 job to finish. Restores original controlDict if
58 - job has finished
59 - controlDict gets modified (by user)
60 - $Script gets killed.
62 The -clear option clears any outstanding $Script for the case.
64 USAGE
65 exit 1
68 unset clearOpt stopOpt
70 # parse options
71 while [ "$#" -gt 0 ]
73 case "$1" in
74 -h | -help)
75 usage
77 -case)
78 [ "$#" -ge 2 ] || usage "'$1' option requires an argument"
79 cd "$2" 2>/dev/null || usage "directory does not exist: '$2'"
80 shift 2
82 -c | -clear)
83 clearOpt=true
84 shift
86 -n | -now)
87 stopOpt=now
88 shift
90 -*)
91 usage "unknown option: '$*'"
94 break
96 esac
97 done
100 # parent directory for normal or parallel
101 case "$PWD" in
102 processor*) caseDir=".." ;;
103 *) caseDir="." ;;
104 esac
106 # check that case directory is writeable
107 [ -w $caseDir ] || {
108 echo "$Script : $caseDir is not writeable"
109 exit 1
112 # check that controlDict is writeable
113 controlDict=$caseDir/system/controlDict
114 [ -w $controlDict ] || {
115 echo "$Script : $controlDict is not writeable"
116 exit 1
119 # need a pid unless with the -clear option
120 if [ "$clearOpt" = true ]
121 then
122 [ $# -eq 0 ] || usage
123 else
124 [ $# -eq 1 ] || usage
125 PID=$1
129 #-------------------------------------------------------------------------------
131 # Functions
133 #-------------------------------------------------------------------------------
135 # getNumberedLine dictionary entry
136 # Prints dictionary entry line + lineno
137 getNumberedLine() {
138 grep -n "^[ \t]*$2[ \t]" $1 | grep -v '^//' | head -1
141 # getLine dictionary entry
142 # Prints dictionary entry line (without lineno)
143 getLine() {
144 getNumberedLine $1 "$2" | sed -e 's/^[^:]*://'
147 # getRawEntry dictionary entry
148 # Prints value of dictionary entry
149 getRawEntry() {
150 getLine $1 "$2" | sed -e "s/^[ \t]*$2[ \t][ \t]*//"
153 # getEntry dictionary entry
154 # Like getRawEntry but strips " and ending ';'
155 getEntry() {
156 getRawEntry $1 "$2" | sed -e 's/^"//' -e 's/;$//' -e 's/"$//'
159 # getKey entryLine
160 # Prints first item on line
161 getKey() {
162 echo "$1" | sed -e 's/[ \t]*\(.*\)[ \t].*/\1/'
166 # setRawEntry dictionary entry newValue
167 # Replaces value of entry
168 setRawEntry() {
169 oldNumLine=`getNumberedLine $1 "$2"`
170 lineNo=`echo "$oldNumLine" | sed -e 's/:.*//'`
171 oldLine=`echo "$oldNumLine" | sed -e 's/^[^:]*://'`
172 oldKey=`getKey "$oldLine"`
173 oldVal=`getRawEntry $1 "$2"`
175 if [ ! "$oldKey" -o ! "$oldVal" -o ! "$oldLine" ]
176 then
177 echo "setRawStringEntry: entry $2 not found in $1"
178 echo "oldKey=$oldKey"
179 echo "lineNo=$lineNo"
180 echo "oldLine=$oldLine"
181 exit 1
184 #echo "oldKey=$oldKey"
185 #echo "lineNo=$lineNo"
186 #echo "oldLine=$oldLine"
187 #echo "oldVal=$oldVal"
188 mv $1 ${1}_tmp
189 sed -e "${lineNo}s/ ${oldVal}/ $3;/" ${1}_tmp > $1
190 rm -f ${1}_tmp
195 # like getEntry but returns true if boolean is logical true
196 getBoolEntry()
198 val=`getEntry $1 $2`
199 case "$val" in
200 y | yes | true | on | 1)
201 return 0
203 n | no | false | off | 0)
204 return 123
207 echo "$Script : getBoolEntry : Illegal boolean value $val in dictionary $1"
208 exit 1
210 esac
213 # processExists pid
214 # Returns true if pid exists.
215 processExists() {
216 ps -u $LOGNAME -o pid | fgrep $1 >/dev/null
219 # Restore controlDict and clean up
220 restoreDict() {
221 trap QUIT TERM INT
223 echo "$Script : Restoring controlDict from controlDict_bak"
224 if [ -r ${controlDict}_bak ]
225 then
226 cp ${controlDict}_bak $controlDict
229 rm -f $pidFile
231 echo "$Script : Exiting"
232 exit 0
236 #-------------------------------------------------------------------------------
238 # Main
240 #-------------------------------------------------------------------------------
242 #-- Force standards behaving ps
243 # Get info on all $USER processes
244 case `uname -s` in
245 HP-UX*)
246 UNIX95=a
247 export UNIX95
249 IRIX*)
250 _XPG=1
251 export _XPG
253 esac
256 # Pid actually running
257 if [ "$clearOpt" != true ]
258 then
259 processExists $PID
260 if [ $? -ne 0 ]
261 then
262 echo "$Script : process $PID not running"
263 exit 1
267 #- runTimeModifiable
268 getBoolEntry $controlDict runTimeModifiable || {
269 echo "$Script : runTimeModifiable not true in dictionary $controlDict"
270 exit 1
274 #- Check if another foamEndJob running
276 if [ "$clear" = true ]
277 then
278 pidFiles=`ls $caseDir/.foamEndJob* 2>/dev/null`
279 for pidFile in $pidFiles
281 pid=`cat $pidFile`
282 if [ "$pid" ]
283 then
284 echo "$Script : found $Script (pid $pid) for OpenFOAM process"
285 echo " case: $PWD/$caseDir"
286 echo "$Script : Killing $Script (pid $pid)"
287 kill $pid
288 rm -f $pidFile
290 done
291 exit 0
294 pidFile=$caseDir/.foamEndJob$PID
295 if [ -f $pidFile ]
296 then
297 pid=`cat $pidFile`
298 if [ "$pid" ]
299 then
300 processExists $pid
301 if [ $? -eq 0 ]
302 then
303 echo "$Script : found running $Script (pid $pid) for OpenFOAM process"
304 echo " case: $PWD/$caseDir"
305 echo " pid : $PID"
306 echo " lock: $pidFile"
307 echo "Remove the lock if this is not the case"
308 exit 1
313 # Mark with my pid
314 echo $$ > $pidFile
317 #- Get controlDict entries
321 #- startTime
322 startTime=`getEntry $controlDict startTime`
323 [ "$startTime" ] || {
324 echo "$Script : startTime not set in dictionary $controlDict"
325 exit 1
328 #- Write interval
329 writeInterval=`getEntry $controlDict writeInterval`
330 [ "$writeInterval" ] || {
331 echo "$Script : writeInterval not set in dictionary $controlDict"
332 exit 1
335 #- stopAt
336 stopAt=`getEntry $controlDict stopAt`
337 [ "$stopAt" ] || {
338 echo "$Script : stopAt not set in dictionary $controlDict"
339 exit 1
342 #- endTime
343 endTime=`getEntry $controlDict endTime`
344 [ "$endTime" ] || {
345 echo "$Script : endTime not set in dictionary $controlDict"
346 exit 1
350 echo "$Script : Read from controlDict:"
351 echo " controlDict : $controlDict"
352 echo " writeInterval : $writeInterval"
353 #echo " startTime : $startTime"
354 echo " stopAt : $stopAt"
355 #echo " endTime : $endTime"
357 echo "$Script : Making backup of controlDict to controlDict_bak"
358 cp $controlDict ${controlDict}_bak
360 #- Set up handler to restore controlDict
361 trap restoreDict QUIT TERM INT
363 if [ "$stopOpt" = now ]
364 then
365 setRawEntry $controlDict stopAt nextWrite
366 setRawEntry $controlDict writeInterval 1
368 echo "$Script : Changed in controlDict:"
369 echo " `getLine $controlDict stopAt`"
370 echo " `getLine $controlDict writeInterval`"
371 else
372 setRawEntry $controlDict stopAt nextWrite
374 echo "$Script : Changed in controlDict:"
375 echo " `getLine $controlDict stopAt`"
380 #- Just to make sure time has changed
381 touch ${controlDict}
383 sleep 5
385 #- Give bak a later date
386 touch ${controlDict}_bak
388 #- Loop a while to give NFS time to update
389 if [ ${controlDict} -nt ${controlDict}_bak ]
390 then
391 echo "$Script : controlDict newer than controlDict_bak"
392 echo "$Script : Waiting for file dates to get updated"
394 iter=0
395 while [ ${controlDict} -nt ${controlDict}_bak ]
397 if [ $iter -ge 120 ]
398 then
399 #- 120*5 sec = 10 mins passed. Give up
400 echo "$Script : File date not yet ok after 10 mins ... giving up"
401 break
403 #- Give _bak a later time
404 touch ${controlDict}_bak
406 #- Give NFS a chance to update time on controlDict.
407 sleep 5
409 iter=`expr $iter + 1`
410 done
414 #- Start waiting until:
415 # - pid finished. Restore controlDict.
416 # - controlDict modified. No restore.
417 # - controlDict_bak removed. No restore.
419 echo "$Script : Waiting for OpenFOAM job $PID to finish ..."
421 while true
423 sleep 5
425 [ -r ${controlDict}_bak ] || {
426 echo "$Script : ${controlDict}_bak disappeared. Exiting without restore"
427 exit 1
430 if [ ${controlDict} -nt ${controlDict}_bak ]
431 then
432 echo "$Script : ${controlDict} modified externally. Exiting without restore"
433 exit 0
436 processExists $PID
437 if [ $? -ne 0 ]
438 then
439 #- Job finished
440 break
442 # echo "OpenFOAM job $PID still running ..."
443 done
445 #- Dictionary restore
446 restoreDict
448 #------------------------------------------------------------------------------