Skip to content

Commit 30b27fc

Browse files
committed
add fixer test and post proc script
1 parent 5c1db62 commit 30b27fc

File tree

3 files changed

+159
-1
lines changed

3 files changed

+159
-1
lines changed

cime_config/tests.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,7 @@
346346
"ERS_Ld5.TL319_oQU240wLI_ais8to30.MPAS_LISIO_JRA1p5.mpaso-ocn_glcshelf",
347347
"SMS_P12x2.ne4pg2_oQU480.WCYCL1850NS.allactive-mach_mods",
348348
"ERS_Ln9.ne4pg2_ne4pg2.F2010-MMF1.eam-mmf_crmout",
349-
"SMS_Lh4.ne4_ne4.F2010-SCREAMv1.eamxx-output-preset-1",
349+
"SMS_Lh4.ne4_ne4.F2010-SCREAMv1.eamxx-output-preset-1--eamxx-fixer_debug_output",
350350
"SMS_Lh4.ne4pg2_ne4pg2.F2010-SCREAMv1.eamxx-output-preset-1--eamxx-prod",
351351
)
352352
},
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
$CIMEROOT/../components/eamxx/scripts/atmchange homme::enable_energy_fixer_debug_info=true -b
2+
./xmlchange POSTRUN_SCRIPT="$CIMEROOT/../components/eamxx/scripts/check-fixer-output"
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
#!/usr/bin/env python3
2+
3+
#"""
4+
#aaa
5+
#"""
6+
7+
import sys, re, glob, pathlib, argparse, gzip
8+
9+
from utils import run_cmd_no_fail, expect, GoodFormatter
10+
11+
###############################################################################
12+
def parse_command_line(args, description):
13+
###############################################################################
14+
parser = argparse.ArgumentParser(
15+
usage="""\n{0} <CASE_DIR> [<param>=<val>] ...
16+
OR
17+
{0} --help
18+
19+
\033[1mEXAMPLES:\033[0m
20+
\033[1;32m# Run hash checker on /my/case/dir \033[0m
21+
> {0} /my/case/dir
22+
""".format(pathlib.Path(args[0]).name),
23+
description=description,
24+
formatter_class=GoodFormatter
25+
)
26+
27+
parser.add_argument(
28+
"case_dir",
29+
help="The test case you want to check"
30+
)
31+
32+
return parser.parse_args(args[1:])
33+
34+
###############################################################################
35+
def readall(fn):
36+
###############################################################################
37+
with open(fn,'r') as f:
38+
txt = f.read()
39+
return txt
40+
41+
###############################################################################
42+
def greptxt(pattern, txt):
43+
###############################################################################
44+
return re.findall('(?:' + pattern + ').*', txt, flags=re.MULTILINE)
45+
46+
###############################################################################
47+
def grep(pattern, fn):
48+
###############################################################################
49+
txt = readall(fn)
50+
return greptxt(pattern, txt)
51+
52+
###############################################################################
53+
def get_log_glob_from_atm_modelio(case_dir):
54+
###############################################################################
55+
filename = case_dir / 'CaseDocs' / 'atm_modelio.nml'
56+
ln = grep('diro = ', filename)[0]
57+
run_dir = pathlib.Path(ln.split()[2].split('"')[1])
58+
ln = grep('logfile = ', filename)[0]
59+
atm_log_fn = ln.split()[2].split('"')[1]
60+
return str(run_dir / '**' / f'atm.log.*')
61+
62+
###############################################################################
63+
64+
# EAMxx:: energy fixer: T tend added to each physics midlevel 0.000222
65+
# EAMxx:: energy fixer: total energy before fix 32486509719.486938
66+
# EAMxx:: energy fixer: rel energy error after fix -7.63290383866757e-18
67+
68+
def get_fixer_lines(fn,start_from_line):
69+
###############################################################################
70+
fixer_lines = []
71+
error_vals = []
72+
73+
lines = []
74+
with gzip.open(fn,'rt') as file:
75+
start_line_found = False
76+
for line in file:
77+
if start_line_found:
78+
lines.append(line)
79+
elif start_from_line in line:
80+
start_line_found = True
81+
82+
i = 0
83+
while i < len(lines):
84+
line = lines[i]
85+
i = i+1
86+
# eamxx hash line has the form "eamxx hash> date=YYYY-MM-DD-XXXXX (STRING), naccum=INT
87+
# The INT at the end says how many of the following line contain hashes for this proc-step
88+
if "EAMxx:: energy fixer: rel energy error" in line:
89+
fixer_lines.append(line)
90+
lline = (line.strip('\n'))
91+
errr = float(lline.split()[8])
92+
error_vals.append(errr)
93+
94+
return fixer_lines,error_vals
95+
96+
###############################################################################
97+
def get_model_start_of_step_lines (atm_log):
98+
###############################################################################
99+
lines = []
100+
with gzip.open(atm_log,'rt') as file:
101+
for line in file:
102+
if "model beg-of-step time" in line:
103+
lines.append(line)
104+
return lines
105+
106+
###############################################################################
107+
def check_fixer_output(case_dir):
108+
###############################################################################
109+
110+
####################### TOLERANCE
111+
TOL = 1e-12
112+
113+
case_dir_p = pathlib.Path(case_dir)
114+
expect(case_dir_p.is_dir(), f"{case_dir} is not a dir")
115+
116+
# Look for the two atm.log files.
117+
glob_pat = get_log_glob_from_atm_modelio(case_dir_p)
118+
atm_fns = glob.glob(glob_pat, recursive=True)
119+
if len(atm_fns) == 0:
120+
print('Could not find atm.log files with glob string {}'.format(glob_pat))
121+
return False
122+
if len(atm_fns) == 1:
123+
print('Found output file {}'.format(atm_fns[0]))
124+
125+
start_line = get_model_start_of_step_lines(atm_fns[0])[0]
126+
127+
print (start_line)
128+
129+
# Extract hash lines, along with their timestamps, but ignore anything
130+
# before the line $start_line
131+
f = atm_fns[0]
132+
fixer_lines,errs = get_fixer_lines(f,start_line)
133+
print('Array of rel. energy errors after energy fixer:',errs)
134+
errsa = [abs(ele) for ele in errs]
135+
mmax = max(errs)
136+
print('Abs. max. for the rel. energy errors:',mmax)
137+
138+
if mmax < TOL:
139+
print('SUCCESS')
140+
return True
141+
else:
142+
print('FAIL, abs. max is less than tolerance, which is ', TOL)
143+
return False
144+
145+
146+
147+
###############################################################################
148+
def _main_func(description):
149+
###############################################################################
150+
success = check_fixer_output(**vars(parse_command_line(sys.argv, description)))
151+
sys.exit(0 if success else 1)
152+
153+
###############################################################################
154+
155+
if (__name__ == "__main__"):
156+
_main_func(__doc__)

0 commit comments

Comments
 (0)