예제 #1
0
def _get_value(val_in, settings_dict, tracers_dict, dict_prefix=''):
    """ Translate val_in (which may be a variable name) to an integer value
    """

    logger = logging.getLogger(__name__)

    # If val_in is an integer, then it is the dimension size and should be returned
    if isinstance(val_in, int):
        return val_in

    # If val_in is a string, then it is a variable name that should be in
    # settings_dict already
    if isinstance(val_in, type(u'')):
        # If val_in = _tracer_list, that's a special case where we want
        # to find a list of tracers according to current settings
        if val_in == '_tracer_list':
            return len(tracers_dict.keys())

        # Otherwise, val_in must refer to a variable that could be
        # in the dictionary with or without the prefix
        try:
            val_out = settings_dict[dict_prefix + val_in]
        except:
            try:
                val_out = settings_dict[val_in]
            except:
                logger.error('Unknown variable name in _get_value: %s' %
                             val_in)
                MARBL_tools.abort(1)
        return val_out

    # Otherwise this is not a well-defined variable request
    logger.error('_get_value() requires integer or string argument')
    MARBL_tools.abort(1)
def _get_array_info(array_size_in, settings_dict, tracers_dict, dict_prefix=''):
    """ Return a list of the proper indexing for array elements, e.g.
            ['(1)', '(2)'] for 1D array or
            ['(1,1)', '(2,1)'] for 2D array
        If array_size_in is not an integer, check to see if it is in settings_dict
    """

    logger = logging.getLogger(__name__)

    # List to be returned:
    str_index = []

    # How many dimensions?
    if isinstance(array_size_in, list):
        # Error checking:
        # This script only support 2D arrays for now
        # (and assumes array_size_in is not a list for 1D arrays)
        if len(array_size_in) > 2:
            logger.error("_get_array_info() only supports 1D and 2D arrays")
            MARBL_tools.abort(1)

        for i in range(0, _get_value(array_size_in[0], settings_dict, tracers_dict, dict_prefix)):
            for j in range(0, _get_value(array_size_in[1], settings_dict, tracers_dict, dict_prefix)):
                str_index.append("(%d,%d)" % (i+1,j+1))
        return str_index

    # How many elements? May be an integer or an entry in self.settings_dict
    for i in range(0, _get_value(array_size_in, settings_dict, tracers_dict, dict_prefix)):
        str_index.append("(%d)" % (i+1))
    return str_index
예제 #3
0
    def __init__(self,
                 default_settings_file,
                 saved_state_vars_source="settings_file",
                 grid=None,
                 input_file=None):
        """ Class constructor: set up a dictionary of config keywords for when multiple
            default values are provided, read the JSON file, and then populate
            self.settings_dict and self.tracers_dict.
        """

        logger = logging.getLogger(__name__)

        # 1. List of configuration keywords to match in JSON if default_default is a dictionary
        self._config_keyword = []
        if grid != None:
            self._config_keyword.append('GRID == "%s"' % grid)
        self._config_keyword.append('SAVED_STATE_VARS_SOURCE == "%s"' %
                                    saved_state_vars_source)

        # 2. Read settings JSON file
        import json
        with open(default_settings_file) as settings_file:
            self._settings = json.load(settings_file)

        # 3 Make sure JSON file adheres to MARBL settings file schema
        if not MARBL_tools.settings_dictionary_is_consistent(self._settings):
            logger.error("%s is not a valid MARBL settings file" %
                         default_settings_file)
            MARBL_tools.abort(1)

        # 4. Read settings input file
        self._input_dict = _parse_input_file(input_file)

        # 5. Use an ordered dictionary for keeping variable, value pairs
        #    Also, tracer information is in its own dictionary (initialized to None)
        from collections import OrderedDict
        self.settings_dict = OrderedDict()
        self.tracers_dict = None
        for cat_name in self.get_category_names():
            for var_name in self.get_variable_names(cat_name):
                self._process_variable_value(cat_name, var_name)
            # 5b. Need tracer count after determining PFT_derived_types, which means
            #     determining which tracers are active
            if cat_name == "PFT_derived_types":
                self.tracers_dict = self._get_tracers()

        # 6. Abort if not all values from input file were processed
        #    (That implies at least one variable from input file was not recognized)
        if (self._input_dict):
            message = "Did not fully parse input file:"
            for varname in self._input_dict.keys():
                message = message + "\n     * Variable %s not found in JSON file" % varname
                message = message + "\n       (this was a case-insensitive lookup)"
            logger.error(message)
            MARBL_tools.abort(1)
예제 #4
0
def _parse_input_file(input_file):
    """ 1. Read an input file; ignore blank lines and non-quoted Fortran comments.
        2. Turn lines of the form
              variable = value
           Into input_dict['variable'] = value
        3. Return input_dict
    """
    input_dict = dict()
    logger = logging.getLogger(__name__)

    try:
        f = open(input_file, "r")
        for line in f:
            # Ignore comments in input file!
            line_loc = _string_to_substring(line, '!')[0]

            # ignore empty lines
            if len(line_loc.lstrip()) == 0:
                continue

            line_list = line_loc.strip().split('=')
            # keys in input_dict are all lowercase to allow case-insensitive match
            var_name = line_list[0].strip().lower()
            value = line_list[1].strip()
            val_array = _string_to_substring(value, ',')
            if len(val_array) > 1:
                # Treat comma-delimited value as an array
                for n, value in enumerate(val_array):
                    suffix = "(%d)" % (n + 1)
                    input_dict[var_name + suffix] = value.strip()
            else:
                # Single value
                input_dict[var_name] = value
        f.close()
    except TypeError:
        # If inputfile == None then the open will result in TypeError
        pass
    except:
        logger.error("input_file '%s' was not found" % input_file)
        MARBL_tools.abort(1)
    return input_dict
예제 #5
0
    def get_category_names(self):
        """ Returns category names as determined by the '_order' key in JSON file
        """

        # Consistency checks:
        # 1. All keys listed in self._settings["_order"] should also be in self._settings.keys()
        for key in self._settings["_order"]:
            if key not in self._settings.keys():
                msg = "ERROR: can not find '" + key + "' in JSON file"
                MARBL_tools.abort(msg)

        # 2. All keys listed in self._settings.keys() should also be in self._settings["_order"]
        #    (except _order itself)
        for key in self._settings.keys():
            if key not in ["_order", "_tracer_list"
                           ] and key not in self._settings["_order"]:
                msg = "ERROR: '" + key + "' is not listed in '_order' and won't be processed"
                MARBL_tools.abort(msg)

        # 3. No duplicates in _order
        unique_keys = []
        for key in self._settings["_order"]:
            if key in unique_keys:
                msg = "ERROR: '" + key + "' appears in '_order' multiple times"
                MARBL_tools.abort(msg)
            unique_keys.append(key)

        return self._settings["_order"]