#!/usr/bin/env python3
"""
Library for implementing getTiming tool which gets timing
information from a run.
"""
from CIME.XML.standard_module_setup import *
from CIME.utils import safe_copy
import datetime, re
logger = logging.getLogger(__name__)
class _GetTimingInfo:
def __init__(self, name):
self.name = name
self.tmin = 0
self.tmax = 0
self.adays = 0
class _TimingParser:
def __init__(self, case, lid="999999-999999"):
self.case = case
self.caseroot = case.get_value("CASEROOT")
self.lid = lid
self.finlines = None
self.fout = None
self.adays = 0
self._driver = case.get_value("COMP_INTERFACE")
self.models = {}
self.ncount = 0
self.nprocs = 0
self.version = -1
def write(self, text):
self.fout.write(text)
def prttime(self, label, offset=None, div=None, coff=-999):
if offset is None:
offset = self.models["CPL"].offset
if div is None:
div = self.adays
datalen = 20
cstr = "<---->"
clen = len(cstr)
minval, maxval, found = self.gettime(label)
if div >= 1.0:
mind = minval / div
maxd = maxval / div
else:
mind = minval
maxd = maxval
pstrlen = 25
if mind >= 0 and maxd >= 0 and found:
if coff >= 0:
zoff = pstrlen + coff + int((datalen - clen) / 2)
csp = offset - coff - int((datalen - clen) / 2)
self.write(
" {label:<{width1}}{cstr:<{width2}} {minv:8.3f}:{maxv:8.3f} \n".format(
label=label,
width1=zoff,
cstr=cstr,
width2=csp,
minv=mind,
maxv=maxd,
)
)
else:
zoff = pstrlen + offset
self.write(
" {label:<{width1}} {minv:8.3f}:{maxv:8.3f} \n".format(
label=label, width1=zoff, minv=mind, maxv=maxd
)
)
def gettime2(self, heading_padded):
if self._driver == "mct" or self._driver == "moab":
return self._gettime2_mct(heading_padded)
elif self._driver == "nuopc":
if self.version < 0:
self._get_esmf_profile_version()
return self._gettime2_nuopc()
def _gettime2_mct(self, heading_padded):
nprocs = 0
ncount = 0
heading = '"' + heading_padded.strip() + '"'
for line in self.finlines:
m = re.match(r"\s*{}\s+\S\s+(\d+)\s*\d+\s*(\S+)".format(heading), line)
if m:
nprocs = int(float(m.groups()[0]))
ncount = int(float(m.groups()[1]))
return (nprocs, ncount)
else:
m = re.match(r"\s*{}\s+\S\s+(\d+)\s".format(heading), line)
if m:
nprocs = 1
ncount = int(float(m.groups()[0]))
return (nprocs, ncount)
return (0, 0)
def _gettime2_nuopc(self):
self.nprocs = 0
self.ncount = 0
if self.version < 0:
self._get_esmf_profile_version()
if self.version == 0:
expression = re.compile(r"\s*\[ATM]\s*RunPhase1\s+(\d+)\s+(\d+)")
else:
expression = re.compile(r"\s*\[ATM]\s*RunPhase1\s+\d+\s+(\d+)\s+(\d+)")
for line in self.finlines:
match = expression.match(line)
if match:
self.nprocs = int(match.group(1))
self.ncount = int(match.group(2))
return (self.nprocs, self.ncount)
return (0, 0)
def gettime(self, heading_padded):
if self._driver == "mct" or self._driver == "moab":
return self._gettime_mct(heading_padded)
elif self._driver == "nuopc":
if self.version < 0:
self._get_esmf_profile_version()
return self._gettime_nuopc(heading_padded)
def _gettime_mct(self, heading_padded):
found = False
heading = '"' + heading_padded.strip() + '"'
minval = 0
maxval = 0
for line in self.finlines:
m = re.match(
r"\s*{}\s+\S\s+\d+\s*\d+\s*\S+\s*\S+\s*(\d*\.\d+)\s*\(.*\)\s*(\d*\.\d+)\s*\(.*\)".format(
heading
),
line,
)
if m:
maxval = float(m.groups()[0])
minval = float(m.groups()[1])
found = True
return (minval, maxval, found)
return (0, 0, False)
def _get_esmf_profile_version(self):
"""
Prior to ESMF8_3_0_beta_snapshot_04 the PEs column was not in ESMF_Profile.summary
this routine looks for that in the header field to determine if this file was produced
by a newer (version 1) or older (version 0) ESMF library.
"""
expect(self.finlines, " No ESMF_Profile.summary file found")
for line in self.finlines:
if line.startswith("Region"):
if "PEs" in line:
self.version = 1
else:
self.version = 0
def _gettime_nuopc(self, heading, instance="0001"):
if instance == "":
instance = "0001"
minval = 0
maxval = 0
m = None
timeline = []
# PETs Count Mean (s) Min (s) Min PET Max (s) Max PET
timeline.append(
re.compile(
r"\s*{}\s+\d+\s+\d+\s+(\d*\.\d+)\s+(\d*\.\d+)\s+\d+\s+(\d*\.\d+)\s+\d+".format(
re.escape(heading)
)
)
)
# PETs PEs Count Mean (s) Min (s) Min PET Max (s) Max PET
timeline.append(
re.compile(
r"\s*{}\s+\d+\s+\d+\s+\d+\s+(\d*\.\d+)\s+(\d*\.\d+)\s+\d+\s+(\d*\.\d+)\s+\d+".format(
re.escape(heading)
)
)
)
phase = None
for line in self.finlines:
phase = self._get_nuopc_phase(line, instance, phase)
if phase != "run" and not "[ensemble]" in heading:
continue
if heading in line:
m = timeline[self.version].match(line)
if m:
minval = float(m.group(2))
maxval = float(m.group(3))
return (minval, maxval, True)
else:
expect(False, "Parsing error in ESMF_Profile.summary file")
return (0, 0, False)
@staticmethod
def _get_nuopc_phase(line, instance, phase):
if "[ensemble] Init 1" in line:
phase = "init"
elif "[ESM" + instance + "] RunPhase1" in line:
phase = "run"
elif "[ESM" + instance + "] Finalize" in line:
phase = "finalize"
elif "[ESM" in line and "RunPhase1" in line:
phase = "other"
return phase
def getMEDtime(self, instance):
if instance == "":
instance = "0001"
med_phase_line = []
med_connector_line = []
med_fraction_line = []
med_phase_line.append(
re.compile(r"\s*(\[MED\] med_phases\S+)\s+\d+\s+\d+\s+(\d*\.\d+)\s+")
)
med_connector_line.append(
re.compile(r"\s*(\[MED\] med_connectors\S+)\s+\d+\s+\d+\s+(\d*\.\d+)\s+")
)
med_fraction_line.append(
re.compile(r"\s*(\[MED\] med_fraction\S+)\s+\d+\s+\d+\s+(\d*\.\d+)\s+")
)
med_phase_line.append(
re.compile(r"\s*(\[MED\] med_phases\S+)\s+\d+\s+\d+\s+\d+\s+(\d*\.\d+)\s+")
)
med_connector_line.append(
re.compile(
r"\s*(\[MED\] med_connectors\S+)\s+\d+\s+\d+\s+\d+\s+(\d*\.\d+)\s+"
)
)
med_fraction_line.append(
re.compile(
r"\s*(\[MED\] med_fraction\S+)\s+\d+\s+\d+\s+\d+\s+(\d*\.\d+)\s+"
)
)
m = None
minval = 0
maxval = 0
phase = None
for line in self.finlines:
phase = self._get_nuopc_phase(line, instance, phase)
if phase != "run":
continue
m = med_phase_line[self.version].match(line)
if not m:
m = med_connector_line[self.version].match(line)
if not m:
m = med_fraction_line[self.version].match(line)
if m:
minval += float(m.group(2))
maxval += float(m.group(2))
return (minval, maxval)
def getCOMMtime(self, instance):
if instance == "":
instance = "0001"
comm_line = []
comm_line.append(
re.compile(r"\s*(\[\S+-TO-\S+\] RunPhase1)\s+\d+\s+\d+\s+(\d*\.\d+)\s+")
)
comm_line.append(
re.compile(
r"\s*(\[\S+-TO-\S+\] RunPhase1)\s+\d+\s+\d+\s+\d+\s+(\d*\.\d+)\s+"
)
)
m = None
maxval = 0
phase = None
for line in self.finlines:
phase = self._get_nuopc_phase(line, instance, phase)
if phase != "run":
continue
m = comm_line[self.version].match(line)
if m:
heading = m.group(1)
maxv = float(m.group(2))
maxval += maxv
logger.debug("{} time={} sum={}".format(heading, maxv, maxval))
return maxval
def getTiming(self):
ninst = 1
multi_driver = self.case.get_value("MULTI_DRIVER")
if multi_driver:
ninst = self.case.get_value("NINST_MAX")
if ninst > 1:
for inst in range(ninst):
self._getTiming(inst + 1)
else:
self._getTiming()
def _getTiming(self, inst=0):
components = self.case.get_values("COMP_CLASSES")
for s in components:
self.models[s] = _GetTimingInfo(s)
atm = None
lnd = None
rof = None
ice = None
ocn = None
glc = None
cpl = None
if "ATM" in self.models:
atm = self.models["ATM"]
if "LND" in self.models:
lnd = self.models["LND"]
if "ROF" in self.models:
rof = self.models["ROF"]
if "ICE" in self.models:
ice = self.models["ICE"]
if "OCN" in self.models:
ocn = self.models["OCN"]
if "GLC" in self.models:
glc = self.models["GLC"]
if "CPL" in self.models:
cpl = self.models["CPL"]
cime_model = self.case.get_value("MODEL")
caseid = self.case.get_value("CASE")
mach = self.case.get_value("MACH")
user = self.case.get_value("USER")
continue_run = self.case.get_value("CONTINUE_RUN")
rundir = self.case.get_value("RUNDIR")
run_type = self.case.get_value("RUN_TYPE")
ncpl_base_period = self.case.get_value("NCPL_BASE_PERIOD")
ncpl = 0
ocn_ncpl = None
for compclass in self.case.get_values("COMP_CLASSES"):
comp_ncpl = self.case.get_value("{}_NCPL".format(compclass))
if compclass == "OCN":
ocn_ncpl = comp_ncpl
if comp_ncpl is not None:
ncpl = max(ncpl, comp_ncpl)
compset = self.case.get_value("COMPSET")
if compset is None:
compset = ""
grid = self.case.get_value("GRID")
run_type = self.case.get_value("RUN_TYPE")
stop_option = self.case.get_value("STOP_OPTION")
stop_n = self.case.get_value("STOP_N")
cost_pes = self.case.get_value("COST_PES")
costpes_per_node = self.case.get_value("COSTPES_PER_NODE")
totalpes = self.case.get_value("TOTALPES")
max_mpitasks_per_node = self.case.get_value("MAX_MPITASKS_PER_NODE")
smt_factor = max(
1, int(self.case.get_value("MAX_TASKS_PER_NODE") / max_mpitasks_per_node)
)
if cost_pes > 0:
pecost = cost_pes
elif costpes_per_node:
pecost = self.case.num_nodes * costpes_per_node
else:
pecost = totalpes
for m in self.models.values():
for key in ["NTASKS", "ROOTPE", "PSTRID", "NTHRDS", "NINST"]:
if key == "NINST" and m.name == "CPL":
m.ninst = 1
else:
setattr(
m,
key.lower(),
int(self.case.get_value("{}_{}".format(key, m.name))),
)
m.comp = self.case.get_value("COMP_{}".format(m.name))
m.pemax = m.rootpe + m.ntasks * m.pstrid - 1
now = datetime.datetime.ctime(datetime.datetime.now())
inittype = "FALSE"
if (run_type == "startup" or run_type == "hybrid") and not continue_run:
inittype = "TRUE"
if inst > 0:
inst_label = "_{:04d}".format(inst)
else:
inst_label = ""
if self._driver == "mct" or self._driver == "moab":
binfilename = os.path.join(
rundir, "timing", "model_timing{}_stats".format(inst_label)
)
finfilename = os.path.join(
self.caseroot,
"timing",
"{}_timing{}_stats.{}".format(cime_model, inst_label, self.lid),
)
elif self._driver == "nuopc":
binfilename = os.path.join(rundir, "ESMF_Profile.summary")
finfilename = os.path.join(
self.caseroot,
"timing",
"{}.ESMF_Profile.summary.{}".format(cime_model, self.lid),
)
foutfilename = os.path.join(
self.caseroot,
"timing",
"{}_timing{}.{}.{}".format(cime_model, inst_label, caseid, self.lid),
)
timingDir = os.path.join(self.caseroot, "timing")
if not os.path.isfile(binfilename):
logger.warning("No timing file found in run directory")
return
if not os.path.isdir(timingDir):
os.makedirs(timingDir)
safe_copy(binfilename, finfilename)
os.chdir(self.caseroot)
try:
fin = open(finfilename, "r")
self.finlines = fin.readlines()
fin.close()
except Exception as e:
logger.critical("Unable to open file {}".format(finfilename))
raise e
tlen = 1.0
if ncpl_base_period == "decade":
tlen = 3650.0
elif ncpl_base_period == "year":
tlen = 365.0
elif ncpl_base_period == "day":
tlen = 1.0
elif ncpl_base_period == "hour":
tlen = 1.0 / 24.0
else:
logger.warning("Unknown NCPL_BASE_PERIOD={}".format(ncpl_base_period))
# at this point the routine becomes driver specific
if self._driver == "mct" or self._driver == "moab":
nprocs, ncount = self.gettime2("CPL:CLOCK_ADVANCE ")
nsteps = ncount / nprocs
elif self._driver == "nuopc":
nprocs, nsteps = self.gettime2("")
adays = nsteps * tlen / ncpl
odays = nsteps * tlen / ncpl
if ocn_ncpl and inittype == "TRUE":
odays = odays - (tlen / ocn_ncpl)
peminmax = max([m.rootpe for m in self.models.values()]) + 1
if ncpl_base_period in ["decade", "year", "day"] and int(adays) > 0:
adays = int(adays)
if tlen % ocn_ncpl == 0:
odays = int(odays)
self.adays = adays
maxoffset = 40
extraoff = 20
for m in self.models.values():
m.offset = int((maxoffset * m.rootpe) / peminmax) + extraoff
if cpl:
cpl.offset = 0
try:
self.fout = open(foutfilename, "w")
except Exception as e:
logger.critical("Could not open file for writing: {}".format(foutfilename))
raise e
self.write("---------------- TIMING PROFILE ---------------------\n")
self.write(" Case : {}\n".format(caseid))
self.write(" LID : {}\n".format(self.lid))
self.write(" Machine : {}\n".format(mach))
self.write(" Caseroot : {}\n".format(self.caseroot))
self.write(" Timeroot : {}/Tools\n".format(self.caseroot))
self.write(" User : {}\n".format(user))
self.write(" Curr Date : {}\n".format(now))
if self._driver == "nuopc":
self.write(" Driver : CMEPS\n")
elif self._driver == "mct" or self._driver == "moab":
self.write(" Driver : CPL7\n")
self.write(" grid : {}\n".format(grid))
self.write(" compset : {}\n".format(compset))
self.write(
" run type : {}, continue_run = {} (inittype = {})\n".format(
run_type, str(continue_run).upper(), inittype
)
)
self.write(" stop option : {}, stop_n = {}\n".format(stop_option, stop_n))
self.write(" run length : {} days ({} for ocean)\n\n".format(adays, odays))
self.write(
" component comp_pes root_pe tasks "
"x threads"
" instances (stride) \n"
)
self.write(
" --------- ------ ------- ------ "
"------ --------- ------ \n"
)
maxthrds = 0
xmax = 0
for k in self.case.get_values("COMP_CLASSES"):
m = self.models[k]
if m.comp == "cpl":
comp_label = m.comp + inst_label
else:
comp_label = m.comp
self.write(
" {} = {:<8s} {:<6d} {:<6d} {:<6d} x {:<6d} {:<6d} ({:<6d}) \n".format(
m.name.lower(),
comp_label,
(m.ntasks * m.nthrds),
m.rootpe,
m.ntasks,
m.nthrds,
m.ninst,
m.pstrid,
)
)
if m.nthrds > maxthrds:
maxthrds = m.nthrds
if self._driver == "nuopc":
for k in components:
m = self.models[k]
if k != "CPL":
m.tmin, m.tmax, _ = self._gettime_nuopc(
" [{}] RunPhase1 ".format(m.name), inst_label[1:]
)
else:
m.tmin, m.tmax = self.getMEDtime(inst_label[1:])
nmax = self.gettime("[ensemble] Init 1")[1]
tmax = self.gettime("[ensemble] RunPhase1")[1]
fmax = self.gettime("[ensemble] FinalizePhase1")[1]
xmax = self.getCOMMtime(inst_label[1:])
if self._driver == "mct" or self._driver == "moab":
for k in components:
if k != "CPL":
m = self.models[k]
m.tmin, m.tmax, _ = self.gettime(" CPL:{}_RUN ".format(m.name))
nmax = self.gettime(" CPL:INIT ")[1]
tmax = self.gettime(" CPL:RUN_LOOP ")[1]
wtmin = self.gettime(" CPL:TPROF_WRITE ")[0]
fmax = self.gettime(" CPL:FINAL ")[1]
otmin, otmax, _ = self.gettime(" CPL:OCNT_RUN ")
# pick OCNT_RUN for tight coupling
if otmax > ocn.tmax:
ocn.tmin = otmin
ocn.tmax = otmax
cpl.tmin, cpl.tmax, _ = self.gettime(" CPL:RUN ")
xmax = self.gettime(" CPL:COMM ")[1]
ocnwaittime = self.gettime(" CPL:C2O_INITWAIT")[0]
if odays != 0:
ocnrunitime = ocn.tmax * (adays / odays - 1.0)
else:
ocnrunitime = 0.0
correction = max(0, ocnrunitime - ocnwaittime)
tmax = tmax + wtmin + correction
ocn.tmax += ocnrunitime
for m in self.models.values():
m.tmaxr = 0
if m.tmax > 0:
m.tmaxr = adays * 86400.0 / (m.tmax * 365.0)
xmaxr = 0
if xmax > 0:
xmaxr = adays * 86400.0 / (xmax * 365.0)
tmaxr = 0
if tmax > 0:
tmaxr = adays * 86400.0 / (tmax * 365.0)
self.write("\n")
self.write(" total pes active : {} \n".format(totalpes * smt_factor))
self.write(" mpi tasks per node : {} \n".format(max_mpitasks_per_node))
self.write(" pe count for cost estimate : {} \n".format(pecost))
self.write("\n")
self.write(" Overall Metrics: \n")
if adays > 0:
self.write(
" Model Cost: {:10.2f} pe-hrs/simulated_year \n".format(
(tmax * 365.0 * pecost) / (3600.0 * adays)
)
)
if tmax > 0:
self.write(
" Model Throughput: {:10.2f} simulated_years/day \n".format(
(86400.0 * adays) / (tmax * 365.0)
)
)
self.write("\n")
self.write(" Init Time : {:10.3f} seconds \n".format(nmax))
if adays > 0:
self.write(
" Run Time : {:10.3f} seconds {:10.3f} seconds/day \n".format(
tmax, tmax / adays
)
)
self.write(" Final Time : {:10.3f} seconds \n".format(fmax))
self.write("\n")
if self._driver == "mct" or self._driver == "moab":
self.write(
" Actual Ocn Init Wait Time : {:10.3f} seconds \n".format(
ocnwaittime
)
)
self.write(
" Estimated Ocn Init Run Time : {:10.3f} seconds \n".format(
ocnrunitime
)
)
self.write(
" Estimated Run Time Correction : {:10.3f} seconds \n".format(
correction
)
)
self.write(
" (This correction has been applied to the ocean and"
" total run times) \n"
)
self.write("\n")
self.write(
"Runs Time in total seconds, seconds/model-day, and"
" model-years/wall-day \n"
)
self.write(
"CPL Run Time represents time in CPL pes alone, "
"not including time associated with data exchange "
"with other components \n"
)
self.write("\n")
if adays > 0:
self.write(
" TOT Run Time: {:10.3f} seconds {:10.3f} seconds/mday {:10.2f} myears/wday \n".format(
tmax, tmax / adays, tmaxr
)
)
for k in self.case.get_values("COMP_CLASSES"):
m = self.models[k]
self.write(
" {} Run Time: {:10.3f} seconds {:10.3f} seconds/mday {:10.2f} myears/wday \n".format(
k, m.tmax, m.tmax / adays, m.tmaxr
)
)
self.write(
" CPL COMM Time: {:10.3f} seconds {:10.3f} seconds/mday {:10.2f} myears/wday \n".format(
xmax, xmax / adays, xmaxr
)
)
pstrlen = 25
hoffset = 1
self.write(" NOTE: min:max driver timers (seconds/day): \n")
for k in self.case.get_values("COMP_CLASSES"):
m = self.models[k]
xspace = (pstrlen + hoffset + m.offset) * " "
self.write(
" {} {} (pes {:d} to {:d}) \n".format(xspace, k, m.rootpe, m.pemax)
)
self.write("\n")
self.prttime(" CPL:CLOCK_ADVANCE ")
self.prttime(" CPL:OCNPRE1_BARRIER ")
self.prttime(" CPL:OCNPRE1 ")
self.prttime(" CPL:ATMOCN1_BARRIER ")
self.prttime(" CPL:ATMOCN1 ")
self.prttime(" CPL:OCNPREP_BARRIER ")
self.prttime(" CPL:OCNPREP ")
self.prttime(
" CPL:C2O_BARRIER ", offset=ocn.offset, div=odays, coff=cpl.offset
)
self.prttime(" CPL:C2O ", offset=ocn.offset, div=odays, coff=cpl.offset)
self.prttime(" CPL:LNDPREP_BARRIER ")
self.prttime(" CPL:LNDPREP ")
self.prttime(" CPL:C2L_BARRIER ", offset=lnd.offset, coff=cpl.offset)
self.prttime(" CPL:C2L ", offset=lnd.offset, coff=cpl.offset)
self.prttime(" CPL:ICEPREP_BARRIER ")
self.prttime(" CPL:ICEPREP ")
self.prttime(" CPL:C2I_BARRIER ", offset=ice.offset, coff=cpl.offset)
self.prttime(" CPL:C2I ", offset=ice.offset, coff=cpl.offset)
self.prttime(" CPL:WAVPREP_BARRIER ")
self.prttime(" CPL:WAVPREP ")
self.prttime(" CPL:C2W_BARRIER ", offset=ice.offset, coff=cpl.offset)
self.prttime(" CPL:C2W ", offset=ice.offset, coff=cpl.offset)
self.prttime(" CPL:ROFPREP_BARRIER ")
self.prttime(" CPL:ROFPREP ")
self.prttime(" CPL:C2R_BARRIER ", offset=rof.offset, coff=cpl.offset)
self.prttime(" CPL:C2R ", offset=rof.offset, coff=cpl.offset)
self.prttime(" CPL:ICE_RUN_BARRIER ", offset=ice.offset)
self.prttime(" CPL:ICE_RUN ", offset=ice.offset)
self.prttime(" CPL:LND_RUN_BARRIER ", offset=lnd.offset)
self.prttime(" CPL:LND_RUN ", offset=lnd.offset)
self.prttime(" CPL:ROF_RUN_BARRIER ", offset=rof.offset)
self.prttime(" CPL:ROF_RUN ", offset=rof.offset)
self.prttime(" CPL:WAV_RUN_BARRIER ", offset=rof.offset)
self.prttime(" CPL:WAV_RUN ", offset=rof.offset)
self.prttime(" CPL:OCNT_RUN_BARRIER ", offset=ocn.offset, div=odays)
self.prttime(" CPL:OCNT_RUN ", offset=ocn.offset, div=odays)
self.prttime(
" CPL:O2CT_BARRIER ", offset=ocn.offset, div=odays, coff=cpl.offset
)
self.prttime(" CPL:O2CT ", offset=ocn.offset, div=odays, coff=cpl.offset)
self.prttime(" CPL:OCNPOSTT_BARRIER ")
self.prttime(" CPL:OCNPOSTT ")
self.prttime(" CPL:ATMOCNP_BARRIER ")
self.prttime(" CPL:ATMOCNP ")
self.prttime(" CPL:L2C_BARRIER ", offset=lnd.offset, coff=cpl.offset)
self.prttime(" CPL:L2C ", offset=lnd.offset, div=cpl.offset)
self.prttime(" CPL:LNDPOST_BARRIER ")
self.prttime(" CPL:LNDPOST ")
self.prttime(" CPL:GLCPREP_BARRIER ")
self.prttime(" CPL:GLCPREP ")
self.prttime(" CPL:C2G_BARRIER ", offset=glc.offset, coff=cpl.offset)
self.prttime(" CPL:C2G ", offset=glc.offset, coff=cpl.offset)
self.prttime(" CPL:R2C_BARRIER ", offset=rof.offset, coff=cpl.offset)
self.prttime(" CPL:R2C ", offset=rof.offset, coff=cpl.offset)
self.prttime(" CPL:ROFPOST_BARRIER ")
self.prttime(" CPL:ROFPOST ")
self.prttime(" CPL:BUDGET1_BARRIER ")
self.prttime(" CPL:BUDGET1 ")
self.prttime(" CPL:I2C_BARRIER ", offset=ice.offset, coff=cpl.offset)
self.prttime(" CPL:I2C ", offset=ice.offset, coff=cpl.offset)
self.prttime(" CPL:ICEPOST_BARRIER ")
self.prttime(" CPL:ICEPOST ")
self.prttime(" CPL:FRACSET_BARRIER ")
self.prttime(" CPL:FRACSET ")
self.prttime(" CPL:ATMOCN2_BARRIER ")
self.prttime(" CPL:ATMOCN2 ")
self.prttime(" CPL:OCNPRE2_BARRIER ")
self.prttime(" CPL:OCNPRE2 ")
self.prttime(
" CPL:C2O2_BARRIER ", offset=ocn.offset, div=odays, coff=cpl.offset
)
self.prttime(" CPL:C2O2 ", offset=ocn.offset, div=odays, coff=cpl.offset)
self.prttime(" CPL:ATMOCNQ_BARRIER")
self.prttime(" CPL:ATMOCNQ ")
self.prttime(" CPL:ATMPREP_BARRIER ")
self.prttime(" CPL:ATMPREP ")
self.prttime(" CPL:C2A_BARRIER ", offset=atm.offset, coff=cpl.offset)
self.prttime(" CPL:C2A ", offset=atm.offset, coff=cpl.offset)
self.prttime(" CPL:OCN_RUN_BARRIER ", offset=ocn.offset, div=odays)
self.prttime(" CPL:OCN_RUN ", offset=ocn.offset, div=odays)
self.prttime(" CPL:ATM_RUN_BARRIER ", offset=atm.offset)
self.prttime(" CPL:ATM_RUN ", offset=atm.offset)
self.prttime(" CPL:GLC_RUN_BARRIER ", offset=glc.offset)
self.prttime(" CPL:GLC_RUN ", offset=glc.offset)
self.prttime(" CPL:W2C_BARRIER ", offset=glc.offset, coff=cpl.offset)
self.prttime(" CPL:W2C ", offset=glc.offset, coff=cpl.offset)
self.prttime(" CPL:WAVPOST_BARRIER ")
self.prttime(" CPL:WAVPOST ", cpl.offset)
self.prttime(" CPL:G2C_BARRIER ", offset=glc.offset, coff=cpl.offset)
self.prttime(" CPL:G2C ", offset=glc.offset, coff=cpl.offset)
self.prttime(" CPL:GLCPOST_BARRIER ")
self.prttime(" CPL:GLCPOST ")
self.prttime(" CPL:A2C_BARRIER ", offset=atm.offset, coff=cpl.offset)
self.prttime(" CPL:A2C ", offset=atm.offset, coff=cpl.offset)
self.prttime(" CPL:ATMPOST_BARRIER ")
self.prttime(" CPL:ATMPOST ")
self.prttime(" CPL:BUDGET2_BARRIER ")
self.prttime(" CPL:BUDGET2 ")
self.prttime(" CPL:BUDGET3_BARRIER ")
self.prttime(" CPL:BUDGET3 ")
self.prttime(" CPL:BUDGETF_BARRIER ")
self.prttime(" CPL:BUDGETF ")
self.prttime(
" CPL:O2C_BARRIER ", offset=ocn.offset, div=odays, coff=cpl.offset
)
self.prttime(" CPL:O2C ", offset=ocn.offset, div=odays, coff=cpl.offset)
self.prttime(" CPL:OCNPOST_BARRIER ")
self.prttime(" CPL:OCNPOST ")
self.prttime(" CPL:RESTART_BARRIER ")
self.prttime(" CPL:RESTART")
self.prttime(" CPL:HISTORY_BARRIER ")
self.prttime(" CPL:HISTORY ")
self.prttime(" CPL:TSTAMP_WRITE ")
self.prttime(" CPL:TPROF_WRITE ")
self.prttime(" CPL:RUN_LOOP_BSTOP ")
self.write("\n\n")
self.write("More info on coupler timing:\n")
self.write("\n")
self.prttime(" CPL:OCNPRE1 ")
self.prttime(" CPL:ocnpre1_atm2ocn ")
self.write("\n")
self.prttime(" CPL:OCNPREP ")
self.prttime(" CPL:OCNPRE2 ")
self.prttime(" CPL:ocnprep_avg ")
self.prttime(" CPL:ocnprep_diagav ")
self.write("\n")
self.prttime(" CPL:LNDPREP ")
self.prttime(" CPL:lndprep_atm2lnd ")
self.prttime(" CPL:lndprep_mrgx2l ")
self.prttime(" CPL:lndprep_diagav ")
self.write("\n")
self.prttime(" CPL:ICEPREP ")
self.prttime(" CPL:iceprep_ocn2ice ")
self.prttime(" CPL:iceprep_atm2ice ")
self.prttime(" CPL:iceprep_mrgx2i ")
self.prttime(" CPL:iceprep_diagav ")
self.write("\n")
self.prttime(" CPL:WAVPREP ")
self.prttime(" CPL:wavprep_atm2wav ")
self.prttime(" CPL:wavprep_ocn2wav ")
self.prttime(" CPL:wavprep_ice2wav ")
self.prttime(" CPL:wavprep_mrgx2w ")
self.prttime(" CPL:wavprep_diagav ")
self.write("\n")
self.prttime(" CPL:ROFPREP ")
self.prttime(" CPL:rofprep_l2xavg ")
self.prttime(" CPL:rofprep_lnd2rof ")
self.prttime(" CPL:rofprep_mrgx2r ")
self.prttime(" CPL:rofprep_diagav ")
self.write("\n")
self.prttime(" CPL:GLCPREP ")
self.prttime(" CPL:glcprep_avg ")
self.prttime(" CPL:glcprep_lnd2glc ")
self.prttime(" CPL:glcprep_mrgx2g ")
self.prttime(" CPL:glcprep_diagav ")
self.write("\n")
self.prttime(" CPL:ATMPREP ")
self.prttime(" CPL:atmprep_xao2atm ")
self.prttime(" CPL:atmprep_ocn2atm ")
self.prttime(" CPL:atmprep_alb2atm ")
self.prttime(" CPL:atmprep_ice2atm ")
self.prttime(" CPL:atmprep_lnd2atm ")
self.prttime(" CPL:atmprep_mrgx2a ")
self.prttime(" CPL:atmprep_diagav ")
self.write("\n")
self.prttime(" CPL:ATMOCNP ")
self.prttime(" CPL:ATMOCN1 ")
self.prttime(" CPL:ATMOCN2 ")
self.prttime(" CPL:atmocnp_ice2ocn ")
self.prttime(" CPL:atmocnp_wav2ocn ")
self.prttime(" CPL:atmocnp_fluxo ")
self.prttime(" CPL:atmocnp_fluxe ")
self.prttime(" CPL:atmocnp_mrgx2o ")
self.prttime(" CPL:atmocnp_accum ")
self.prttime(" CPL:atmocnp_ocnalb ")
self.write("\n")
self.prttime(" CPL:ATMOCNQ ")
self.prttime(" CPL:atmocnq_ocn2atm ")
self.prttime(" CPL:atmocnq_fluxa ")
self.prttime(" CPL:atmocnq_atm2ocnf ")
self.write("\n")
self.prttime(" CPL:OCNPOSTT ")
self.prttime(" CPL:OCNPOST ")
self.prttime(" CPL:ocnpost_diagav ")
self.write("\n")
self.prttime(" CPL:LNDPOST ")
self.prttime(" CPL:lndpost_diagav ")
self.prttime(" CPL:lndpost_acc2lr ")
self.prttime(" CPL:lndpost_acc2lg ")
self.write("\n")
self.prttime(" CPL:ROFOST ")
self.prttime(" CPL:rofpost_diagav ")
self.prttime(" CPL:rofpost_histaux ")
self.prttime(" CPL:rofpost_rof2lnd ")
self.prttime(" CPL:rofpost_rof2ice ")
self.prttime(" CPL:rofpost_rof2ocn ")
self.write("\n")
self.prttime(" CPL:ICEPOST ")
self.prttime(" CPL:icepost_diagav ")
self.write("\n")
self.prttime(" CPL:WAVPOST ")
self.prttime(" CPL:wavpost_diagav ")
self.write("\n")
self.prttime(" CPL:GLCPOST ")
self.prttime(" CPL:glcpost_diagav ")
self.prttime(" CPL:glcpost_glc2lnd ")
self.prttime(" CPL:glcpost_glc2ice ")
self.prttime(" CPL:glcpost_glc2ocn ")
self.write("\n")
self.prttime(" CPL:ATMPOST ")
self.prttime(" CPL:atmpost_diagav ")
self.write("\n")
self.prttime(" CPL:BUDGET ")
self.prttime(" CPL:BUDGET1 ")
self.prttime(" CPL:BUDGET2 ")
self.prttime(" CPL:BUDGET3 ")
self.prttime(" CPL:BUDGETF ")
self.write("\n\n")
self.fout.close()
[docs]
def get_timing(case, lid):
parser = _TimingParser(case, lid)
parser.getTiming()