Source code for viscid.readers.ggcm_logfile
"""Loads a ggcm log file
Parses the view info """
from __future__ import print_function
import itertools
import re
import numpy as np
from viscid.readers import vfile
# FIXME: This lookup table is based on an enum in ggcm_mhd.h, ie, the numerical
# values (index in this list) could change in the future - but libmrc
# only writes out the integer value for mhd->ggcm_mhd_fld->mhd_type
# into the log file, so a guess is better than nothing...
MHD_TYPES = ["MT_PRIMITIVE",
# the following have B staggered the openggcm way: [-1..mx[
"MT_SEMI_CONSERVATIVE_GGCM",
# the following have B staggered the "normal" way: [0..mx]
"MT_SEMI_CONSERVATIVE",
"MT_FULLY_CONSERVATIVE",
# cell-centered fully conservative MHD
"MT_FULLY_CONSERVATIVE_CC",
# the multi-moment schemes are cell-centered for all quantities
"MT_GKEYLL"]
[docs]class GGCMLogFile(vfile.VFile): # pylint: disable=W0223
"""Libmrc log file reader
This class looks at the mrc_view info before the run starts
to gather info about libmrc runtime parameters.
Attributes:
watched_classes (list): list of libmrc classes whose parameters
will be loaded
"""
_detector = None
_grid_type = None
watched_classes = ["ggcm_mhd",
"mrc_domain",
"mrc_crds",
"ggcm_mhd_ic",
"ggcm_dipole",
"ggcm_mhd_step",
"ggcm_mhd_fld"]
info = None
def _parse(self):
_info = {}
armed = False
with open(self.fname, 'r') as f:
# find end of view
def is_timestep(s):
return not s.strip().startswith(('cp=', 'step='))
lines_iter = itertools.takewhile(is_timestep, f)
for line in lines_iter:
line = line.strip()
if armed:
try:
key, val = self._parse_param(line)
_info["{0}_{1}".format(armed, key)] = val
except ValueError:
# this is expected for lines that look like
# "-------+------ type -- ???"
# as well as blank lines that mark the end of a
# section
clstype = re.match(r"-+\+-+ type -- (\w+)", line)
if clstype:
_info["{0}_type".format(armed)] = clstype.group(1)
# yes, keep armed, for super's parameters
elif line == "":
armed = False
else:
try:
c = re.match(r"=+ class == (.+)", line).group(1)
c = c.strip()
if c in self.watched_classes:
armed = c
# the next lines just say
# "parameter | value"
# "-----------|------"
# ignore them
next(lines_iter)
next(lines_iter)
except AttributeError:
# not the start of a new class view, that's ok
pass
try:
mhd_type = _info["ggcm_mhd_fld_mhd_type"]
_info["ggcm_mhd_fld_mhd_type_str"] = MHD_TYPES[mhd_type]
except (IndexError, KeyError):
_info["ggcm_mhd_fld_mhd_type_str"] = "UNKNOWN"
self.info = _info
@staticmethod
def _parse_value(s):
"""Parse a parameter and infer its type
Parameters:
s (str): the value of a libmrc parameter
Returns:
Either an int, float, string, or list of mixed types as
inferred by the data
"""
try:
return int(s)
except ValueError:
pass
try:
return float(s)
except ValueError:
pass
s = s.strip()
if re.match(r"\-?[\d\.]+(\s*,\s*\-?[\d\.]+)+", s):
l = s.split(",")
for i, s in enumerate(l):
try:
l[i] = int(s)
except ValueError:
try:
l[i] = float(s)
except ValueError:
l[i] = s.strip()
return np.array(l)
elif re.match(r"[A-Za-z\d\.\-]+(\s*:\s*[A-Za-z\d\.\-]+)+", s):
return s.split(":")
else:
return s
@classmethod
def _parse_param(cls, s):
"""Parse a libmrc view output line
Parameters:
s (str): full line of a parameter in the view
Raises
ValueError: If there is > 1 '|' character in s
"""
key, val = [part.strip() for part in s.split("|")]
val = cls._parse_value(val)
return key, val
[docs] def unload(self, **kwargs):
self.info = {}
super(GGCMLogFile, self).unload(**kwargs)
##
## EOF
##