|
PISM, A Parallel Ice Sheet Model stable 0.4.1779
|
00001 #!/usr/bin/env python 00002 00003 ## @package vfnow 00004 ## \author Ed Bueler and Constantine Khroulev, University of Alaska Fairbanks, USA 00005 ## \brief A script for verification of numerical schemes in PISM. 00006 ## \details It specifies a refinement path for each of Tests ABCDEFGIJKL and runs 00007 ## pismv accordingly. 00008 ## Copyright (C) 2007--2011 Ed Bueler and Constantine Khroulev 00009 ## 00010 ## Organizes the process of verifying PISM. It specifies standard refinement paths for each of the tests described in the user manual. It runs the tests, times them, and summarizes the numerical errors reported at the end. 00011 ## 00012 ## Examples: 00013 ## - \verbatim vfnow.py \endverbatim use one processor and do three levels of refinement; this command is equivalent to \verbatim vfnow.py -n 2 -l 2 -t CGIJ \endverbatim, 00014 ## - \verbatim vfnow.py -n 8 -l 5 -t J --prefix=bin/ --mpido='aprun -n' \endverbatim will use \verbatim aprun -n 8 bin/pismv \endverbatim as the command and do five levels (the maximum) of refinement only on test J, 00015 ## - \verbatim vfnow.py -n 2 -l 3 -t CEIJGKLO \endverbatim uses two processers (cores) and runs in about an hour, 00016 ## - \verbatim vfnow.py -n 40 -l 5 -t ABCDEFGIJKLO \endverbatim will use forty processors to do all possible verification as managed by \c vfnow.py; don't run this unless you have a big computer and you are prepared to wait. 00017 ## For a list of options do \verbatim test/vfnow.py --help \endverbatim. 00018 ## Timing information is given in the \c vfnow.py output so performance, including parallel performance, can be assessed along with accuracy. 00019 00020 import sys, getopt, time, commands 00021 from numpy import array, double, int 00022 00023 ## A class describing a refinement path and command-line options 00024 ## for a particular PISM verification test. 00025 class PISMVerificationTest: 00026 00027 ## max number of levels that will work with 00028 N = 50 00029 ## one-letter test name 00030 name = "" 00031 ## test description 00032 test = "" 00033 ## description of the refinement path 00034 path = "" 00035 Mx = [] 00036 My = [] 00037 ## 31 levels in the ice 00038 Mz = [31] * N 00039 ## no bedrock by default 00040 Mbz = [1] * N 00041 ## extra options (such as -y, -ys, -ssa_rtol) 00042 opts = "" 00043 executable = "pismv" 00044 00045 def build_command(self, exec_prefix, level): 00046 M = zip(self.Mx, self.My, self.Mz, self.Mbz) 00047 00048 if level > len(M): 00049 print "Test %s: Invalid refinement level: %d (only %d are available)" % ( 00050 self.name, level, len(M)) 00051 return "" 00052 00053 grid_options = "-Mx %d -My %d -Mz %d -Mbz %d" % M[level - 1] 00054 return "%s%s -test %s %s %s" % (exec_prefix, self.executable, self.name, grid_options, self.opts) 00055 00056 def run_test(executable, name, level, extra_options = "", debug = False): 00057 try: 00058 test = tests[name] 00059 except: 00060 print "Test %s not found." % name 00061 return 00062 00063 if level == 1: 00064 print " ++++ TEST %s: verifying with %s exact solution ++++\n %s" % ( 00065 test.name, test.test, test.path) 00066 00067 command = test.build_command(executable, level) + " " + extra_options 00068 00069 if debug: 00070 print ' L%d: would try "%s"' % (level, command) 00071 return 00072 else: 00073 print ' L%d: trying "%s"' % (level, command) 00074 00075 # run PISM: 00076 try: 00077 lasttime = time.time() 00078 (status,output) = commands.getstatusoutput(command) 00079 elapsetime = time.time() - lasttime 00080 except KeyboardInterrupt: 00081 sys.exit(2) 00082 if status: 00083 sys.exit(status) 00084 print ' finished in %7.4f seconds; reported numerical errors as follows:' % elapsetime 00085 00086 # process the output: 00087 position = output.find('NUMERICAL ERRORS') 00088 if position >= 0: 00089 report = output[position:output.find('NUM ERRORS DONE')] 00090 endline = report.find('\n') 00091 print ' ' + report[0:endline] 00092 report = report[endline+1:] 00093 while (len(report) > 1) and (endline > 0): 00094 endline = report.find('\n') 00095 if endline == -1: 00096 endline = len(report) 00097 print ' #' + report[0:endline] 00098 report = report[endline+1:] 00099 endline = report.find('\n') 00100 if endline == -1: 00101 endline = len(report) 00102 print ' |' + report[0:endline] 00103 report = report[endline+1:] 00104 else: 00105 print " ERROR: can't find reported numerical error" 00106 sys.exit(99) 00107 00108 00109 def define_refinement_paths(KSPRTOL, SSARTOL): 00110 # Define all the supported refinement paths: 00111 tests = {} 00112 # A 00113 A = PISMVerificationTest() 00114 A.name = "A" 00115 A.test = "steady, marine margin isothermal SIA" 00116 A.path = "(refine dx=53.33,40,26.67,20,13.33,km, dx=dy and Mx=My=31,41,61,81,121)" 00117 A.Mx = [31, 41, 61, 81, 121] 00118 A.My = A.Mx 00119 A.opts = "-y 25000.0" 00120 tests['A'] = A 00121 # B 00122 B = PISMVerificationTest() 00123 B.name = "B" 00124 B.test = "moving margin isothermal SIA (Halfar)" 00125 B.path = "(refine dx=80,60,40,30,20,km, dx=dy and Mx=My=31,41,61,81,121)" 00126 B.Mx = [31, 41, 61, 81, 121] 00127 B.My = B.Mx 00128 B.opts = "-ys 422.45 -y 25000.0" 00129 tests['B'] = B 00130 # C 00131 C = PISMVerificationTest() 00132 C.name = "C" 00133 C.test = "non-zero accumulation moving margin isothermal SIA" 00134 C.path = "(refine dx=50,33.33,25,20,16,km, dx=dy and Mx=My=41,61,81,101,121)" 00135 C.Mx = [41, 61, 81, 101, 121] 00136 C.My = C.Mx 00137 C.opts = "-y 15208.0" 00138 tests['C'] = C 00139 # D 00140 D = PISMVerificationTest() 00141 D.name = "D" 00142 D.test = "time-dependent isothermal SIA" 00143 D.path = "(refine dx=50,33.33,25,20,16.67,km, dx=dy and Mx=My=41,61,81,101,121)" 00144 D.Mx = [41, 61, 81, 101, 121] 00145 D.My = D.Mx 00146 D.opts = "-y 25000.0" 00147 tests['D'] = D 00148 # E 00149 E = PISMVerificationTest() 00150 E.name = "E" 00151 E.test = "steady sliding marine margin isothermal SIA" 00152 E.path = "(refine dx=53.33,40,26.67,20,13.33,km, dx=dy and Mx=My=31,41,61,81,121)" 00153 E.Mx = [31, 41, 61, 81, 121] 00154 E.My = E.Mx 00155 E.opts = "-y 25000.0" 00156 tests['E'] = E 00157 # F 00158 F = PISMVerificationTest() 00159 F.name = "F" 00160 F.test = "steady thermomechanically-coupled SIA" 00161 F.path = "(refine dx=30,20,15,10,7.5,km, dx=dy, dz=66.67,44.44,33.33,22.22,16.67 m\n and Mx=My=Mz=61,91,121,181,241)" 00162 F.Mx = [61, 91, 121, 181, 241] 00163 F.My = F.Mx 00164 F.Mz = F.Mx 00165 F.opts = "-y 25000.0" 00166 tests['F'] = F 00167 # G 00168 G = PISMVerificationTest() 00169 G.name = "G" 00170 G.test = "time-dependent thermomechanically-coupled SIA" 00171 G.path = "(refine dx=30,20,15,10,7.5,km, dx=dy, dz=66.67,44.44,33.33,22.22,16.67 m\n and Mx=My=Mz=61,91,121,181,241)" 00172 G.Mx = [61, 91, 121, 181, 241] 00173 G.My = G.Mx 00174 G.Mz = G.Mx 00175 G.opts = "-y 25000.0" 00176 tests['G'] = G 00177 # H 00178 H = PISMVerificationTest() 00179 H.name = "H" 00180 H.test = "moving margin, isostatic bed, isothermal SIA" 00181 H.path = "(refine dx=80,60,40,30,20,km, dx=dy and Mx=My=31,41,61,81,121)" 00182 H.Mx = [31, 41, 61, 81, 121] 00183 H.My = H.Mx 00184 H.opts = "-bed_def iso -y 60000.0" 00185 tests['H'] = H 00186 # I 00187 I = PISMVerificationTest() 00188 I.name = "I" 00189 I.test = "plastic till ice stream (SSA)" 00190 I.path = "(refine dy=5000,1250,312.5,78.13,19.53,m, My=49,193,769,3073,12289)" 00191 I.Mx = [5] * 5 00192 I.My = [49, 193, 769, 3073, 12289] 00193 I.executable = "ssa_testi" 00194 I.opts = "-ssa_method fd -ssa_rtol %1.e -ksp_rtol %1.e" % (SSARTOL, KSPRTOL) 00195 tests['I'] = I 00196 # J 00197 J = PISMVerificationTest() 00198 J.name = "J" 00199 J.test = "periodic ice shelf (linearized SSA)" 00200 J.path = "(refine dy=5000,1250,312.5,78.13,19.53,m, Mx=49,193,769,3073,12289)" 00201 J.Mx = [49, 98, 196, 392, 784] 00202 J.My = J.Mx 00203 J.Mz = [11] * 5 00204 J.executable = "ssa_testj" 00205 J.opts = "-ssa_method fd -pc_type asm -sub_pc_type lu -ksp_rtol %1.e" % KSPRTOL 00206 tests['J'] = J 00207 # K 00208 K = PISMVerificationTest() 00209 K.name = "K" 00210 K.test = "pure conduction problem in ice and bedrock" 00211 K.path = "(refine dz=100,50,25,12.5,6.25,m, Mz=41,81,161,321,641)" 00212 K.Mx = [8] * 5 00213 K.My = K.Mx 00214 K.Mz = array([41, 81, 161, 321, 641]) 00215 K.Mbz = (K.Mz - 1) / 4 + 1 00216 K.opts = "-y 130000.0 -Lbz 1000 -z_spacing equal" 00217 tests['K'] = K 00218 # L 00219 L = PISMVerificationTest() 00220 L.name = "L" 00221 L.test = "non-flat bed stead isothermal SIA" 00222 L.path = "(refine dx=60,30,20,15,10,km, dx=dy and Mx=My=31,61,91,121,181)" 00223 L.Mx = [31, 61, 91, 121, 181] 00224 L.My = L.Mx 00225 L.opts = "-y 25000.0" 00226 tests['L'] = L 00227 # M 00228 M = PISMVerificationTest() 00229 M.name = "M" 00230 M.test = "annular ice shelf with a calving front (SSA)" 00231 M.path = "(refine dx=50,25,16.666,12.5,8.333 km; dx=dy and My=31,61,91,121,181)" 00232 M.Mx = [31, 61, 91, 121, 181] 00233 M.My = M.Mx 00234 M.Mz = [11] * 5 00235 M.opts = "-ssa_rtol %1.e -ksp_rtol %1.e" % (SSARTOL, KSPRTOL) 00236 tests['M'] = M 00237 # O 00238 O = PISMVerificationTest() 00239 O.name = "O" 00240 O.test = "basal melt rate from conduction problem in ice and bedrock" 00241 O.path = "(refine dz=100,50,25,12.5,6.25,m, Mz=41,81,161,321,641)" 00242 O.Mx = [8] * 5 00243 O.My = O.Mx 00244 O.Mz = array([41, 81, 161, 321, 641]) 00245 O.Mbz = (O.Mz - 1) / 4 + 1 00246 O.opts = "-z_spacing equal -zb_spacing equal -Lbz 1000 -y 1000 -no_mass" 00247 tests['O'] = O 00248 00249 # test K (for a figure in the User's Manual) 00250 K = PISMVerificationTest() 00251 K.name = "K" 00252 K.test = "pure conduction problem in ice and bedrock" 00253 K.path = "(lots of levels)" 00254 K.Mz = array([101, 121, 141, 161, 181, 201, 221, 241, 261, 281, 301, 321]) 00255 K.Mbz = (K.Mz - 1) / 4 + 1 00256 K.Mx = [8] * len(K.Mz) 00257 K.My = K.Mx 00258 K.opts = "-y 130000.0 -Lbz 1000" 00259 tests['K_userman'] = K 00260 00261 # test B (for a figure in the User's Manual) 00262 B = PISMVerificationTest() 00263 B.name = "B" 00264 B.test = "moving margin isothermal SIA (Halfar)" 00265 B.path = "(lots of levels)" 00266 B.Mx = [31, 41, 51, 61, 71, 81, 91, 101, 111, 121] 00267 B.My = B.Mx 00268 B.Mz = [31] * len(B.Mx) 00269 B.Mbz = [1] * len(B.Mx) 00270 B.opts = "-ys 422.45 -y 25000.0" 00271 tests['B_userman'] = B 00272 00273 # test G (for a figure in the User's Manual) 00274 G = PISMVerificationTest() 00275 G.name = "G" 00276 G.test = "time-dependent thermomechanically-coupled SIA" 00277 G.path = "(lots of levels)" 00278 G.Mx = [61, 71, 81, 91, 101, 111, 121, 151, 181] 00279 G.My = G.Mx 00280 G.Mz = G.Mx 00281 G.opts = "-y 25000.0" 00282 tests['G_userman'] = G 00283 00284 # test I (for a figure in the User's Manual) 00285 I = PISMVerificationTest() 00286 I.name = "I" 00287 I.test = "plastic till ice stream (SSA)" 00288 I.path = "(lots of levels)" 00289 I.My = [51, 101, 151, 201, 401, 601, 801, 1001, 1501, 2001, 2501, 3073] 00290 I.Mx = [5] * len(I.My) 00291 I.opts = "-ssa_rtol %1.e -ksp_rtol %1.e" % (SSARTOL, KSPRTOL) 00292 tests['I_userman'] = I 00293 00294 return tests 00295 00296 ##### 00297 ## get options; see --help msg for meaning 00298 ## default settings 00299 KSPRTOL = 1e-12 # for tests I, J, M 00300 SSARTOL = 5e-7 # ditto 00301 nproc = 2 ## default; will not use 'mpiexec' if equal to one 00302 levels = 2 00303 mpi = "mpiexec -np" 00304 prefix = "" 00305 test_names = "CGIJ" 00306 userman_tests = ["B_userman", "G_userman", "K_userman", "I_userman"] 00307 extra_options = "-verbose 1" 00308 do_userman = False 00309 debug = False 00310 try: 00311 opts, args = getopt.getopt(sys.argv[1:], "ep:n:l:t:ur:", 00312 ["eta","prefix=","nproc=","levels=","tests=","userman", "debug", 00313 "uneq","mpido=","report_file=","help","usage"]) 00314 for opt, arg in opts: 00315 if opt in ("-p", "--prefix"): 00316 prefix = arg 00317 elif opt == "--userman": 00318 do_userman = True 00319 elif opt == "--debug": 00320 debug = True 00321 elif opt in ("-m", "--mpido"): 00322 mpi = arg 00323 elif opt in ("-n", "--nproc"): 00324 nproc = int(arg) 00325 elif opt in ("-l", "--levels"): 00326 levels = int(arg) 00327 elif opt in ("-t", "--tests"): 00328 test_names = arg.upper() 00329 elif opt in ("-u", "--uneq"): 00330 extra_options += " -z_spacing quadratic" 00331 elif opt in ("-e", "--eta"): 00332 extra_options += " -eta" 00333 elif opt in ("-r", "--report_file"): 00334 extra_options += " -report_file %s" % arg 00335 elif opt in ("--help", "--usage"): 00336 print """PISM verification script; usage: 00337 -e,--eta= to add '-eta' option to pismv call 00338 -l,--levels= number of levels of verification; '-l 1' fast, '-l 5' slowest 00339 --mpido= specify MPI executable 00340 (e.g. 'mpirun -np' or 'aprun -n' instead of default 'mpiexec -np') 00341 -n,--nproc= specify number of processors to MPI 00342 -p,--prefix= path prefix to pismv executable 00343 -r,--report_file= name of the NetCDF error report file 00344 -t,--tests= verification tests to use: A,B,C,D,E,F,G,H,I,J,K,L,M,O 00345 -u use unequal spaced (quadratic) vertical spacing 00346 --userman run tests necessary to produce figures in the User's Manual 00347 --debug do not run PISM, just print commands 00348 --help prints this message 00349 --usage ditto""" 00350 sys.exit(0) 00351 except getopt.GetoptError: 00352 print 'Incorrect command line arguments' 00353 sys.exit(2) 00354 # should do range checking on option arguments here 00355 00356 if nproc > 1: 00357 predo = "%s %d " % (mpi, nproc) 00358 else: 00359 predo = "" 00360 exec_prefix = predo + prefix 00361 00362 tests = define_refinement_paths(KSPRTOL, SSARTOL) 00363 00364 if do_userman: 00365 print " VFNOW.PY: test(s) %s, using '%s...'\n" % (userman_tests, exec_prefix) + \ 00366 " and ignoring options -t and -l" 00367 for test in userman_tests: 00368 N = len(tests[test].Mx) 00369 for j in range(1, N + 1): 00370 run_test(exec_prefix, test, j, extra_options, debug) 00371 else: 00372 print " VFNOW.PY: test(s) %s, %d refinement level(s), using '%s...'" % ( 00373 test_names, levels, exec_prefix) 00374 00375 for test in test_names: 00376 for j in range(1, levels + 1): 00377 run_test(exec_prefix, test, j, extra_options, debug) 00378
1.7.3