text: #!/usr/bin/env python
  
  """
  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.models = {}
  
      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):
          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 gettime(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 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 = self.models['ATM']
          lnd = self.models['LND']
          rof = self.models['ROF']
          ice = self.models['ICE']
          ocn = self.models['OCN']
          glc = self.models['GLC']
          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
          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 = ''
  
          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))
          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))
  
          nprocs, ncount = self.gettime2('CPL:CLOCK_ADVANCE ')
          nsteps = ncount / nprocs
  
          adays = nsteps*tlen/ncpl
          odays = nsteps*tlen/ncpl
          if 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
          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))
  
          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
          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 *smt_factor), m.rootpe, m.ntasks, m.nthrds, m.ninst, m.pstrid))
              if m.nthrds > maxthrds:
                  maxthrds = m.nthrds
          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]
          for k in components:
              if k != "CPL":
                  m = self.models[k]
              m.tmin, m.tmax, _ = self.gettime(' CPL:{}_RUN '.format(m.name))
          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*maxthrds*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")
          self.write("    Model Cost:         {:10.2f}   pe-hrs/simulated_year \n".format((tmax*365.0*pecost)/(3600.0*adays)))
          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))
          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")
  
          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")
  
          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))
  
          self.write("\n\n---------------- DRIVER TIMING FLOWCHART "
                     "--------------------- \n\n")
  
          pstrlen = 25
          hoffset = 1
          self.write("   NOTE: min:max driver timers (seconds/day):   \n")
  
          for k in ["CPL", "OCN", "LND", "ROF", "ICE", "ATM", "GLC", "WAV"]:
              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()
  
  def get_timing(case, lid):
      parser = _TimingParser(case, lid)
      parser.getTiming()
  