Exemplo n.º 1
0
    def solve_model(self, model_run, store):
        """Solve a ModelRun

        This method first calls :func:`smif.model.SosModel.before_model_run`
        with parameter data, then steps through the model horizon, calling
        :func:`smif.model.SosModel.simulate` with parameter data at each
        timestep.

        Arguments
        ---------
        model_run : :class:`smif.modelrun.ModelRun`
        """
        self.logger.debug("Initialising each of the sector models")
        # Initialise each of the sector models
        data_handle = DataHandle(
            store, model_run.name, None, model_run.model_horizon,
            model_run.sos_model)
        model_run.sos_model.before_model_run(data_handle)

        self.logger.debug("Solving the models over all timesteps: %s",
                          model_run.model_horizon)
        # Solve the models over all timesteps
        for timestep in model_run.model_horizon:
            self.logger.debug('Running model for timestep %s', timestep)

            data_handle = DataHandle(
                store, model_run.name, timestep, model_run.model_horizon,
                model_run.sos_model)
            model_run.sos_model.simulate(data_handle)
        return data_handle
Exemplo n.º 2
0
    def _model_converged(self, model, data_handle):
        """Check a single model's output for convergence

        Compare data output for each param over recent iterations.

        Parameters
        ----------
        model: :class:`smif.model.Model`
        data_handle: :class:`smif.data_layer.DataHandle`

        Returns
        -------
        bool
            True if converged otherwise, False
        """
        prev_data_handle = DataHandle(
            data_handle._store,
            data_handle._modelrun_name,
            data_handle._current_timestep,
            data_handle._timesteps,
            model,
            self._current_iteration - 1,  # access previous iteration
            data_handle._decision_iteration)
        return all(
            np.allclose(data_handle.get_data(param.name),
                        prev_data_handle.get_data(param.name),
                        rtol=self.relative_tolerance,
                        atol=self.absolute_tolerance)
            for param in model.inputs.metadata)
Exemplo n.º 3
0
    def simulate(self, data_handle):
        """Run the SosModel

        Arguments
        ---------
        data_handle: smif.data_layer.DataHandle
            Access state, parameter values, dependency inputs

        Returns
        -------
        results : smif.data_layer.DataHandle
            Access model outputs

        """
        self.check_dependencies()
        run_order = self._get_model_sets_in_run_order()
        self.logger.info("Determined run order as %s",
                         [x.name for x in run_order])
        for model in run_order:
            # get custom data handle for the Model
            model_data_handle = DataHandle(data_handle._store,
                                           data_handle._modelrun_name,
                                           data_handle._current_timestep,
                                           list(data_handle.timesteps), model,
                                           data_handle._modelset_iteration,
                                           data_handle._decision_iteration)
            model.simulate(model_data_handle)
        return data_handle
Exemplo n.º 4
0
 def test_previous_timestep_error(self):
     """should raise error if there's no previous timestep in the list
     """
     data_handle = DataHandle(Mock(), 1, 2015, [2015, 2020], Mock())
     with raises(TimestepResolutionError) as ex:
         data_handle.previous_timestep
     assert 'no previous timestep' in str(ex)
Exemplo n.º 5
0
def _get_model_and_handle(store,
                          model_run_id,
                          model_name,
                          timestep=None,
                          decision=None):
    """Helper method to read model and set up appropriate data handle
    """
    try:
        model_run_config = store.read_model_run(model_run_id)
    except SmifDataNotFoundError:
        logging.error(
            "Model run %s not found. Run 'smif list' to see available model runs.",
            model_run_id)
        sys.exit(1)

    loader = ModelLoader()
    sector_model_config = store.read_model(model_name)
    # absolute path to be crystal clear for ModelLoader when loading python class
    sector_model_config['path'] = os.path.normpath(
        os.path.join(store.model_base_folder, sector_model_config['path']))
    model = loader.load(sector_model_config)

    # DataHandle reads
    # - model run from store to find narratives and scenarios selected
    # - sos model from store to find dependencies and parameters
    # all in order to resolve *input* data locations and *parameter* defaults and values
    data_handle = DataHandle(store=store,
                             model=model,
                             modelrun_name=model_run_id,
                             current_timestep=timestep,
                             timesteps=model_run_config['timesteps'],
                             decision_iteration=decision)
    return model, data_handle
Exemplo n.º 6
0
def get_data_handle(model):
    """Return a data handle for the model
    """
    store = MemoryInterface()
    store.write_sos_model_run({'name': 'test', 'narratives': {}})
    return DataHandle(
        store,
        'test',  # modelrun_name
        2010,  # current_timestep
        [2010, 2011],  # timesteps
        model)
Exemplo n.º 7
0
 def before_model_run(self, data_handle):
     """Initialise each model (passing in parameter data only)
     """
     for model in self.sector_models.values():
         # get custom data handle for the Model
         model_data_handle = DataHandle(data_handle._store,
                                        data_handle._modelrun_name,
                                        data_handle._current_timestep,
                                        data_handle._timesteps, model,
                                        data_handle._modelset_iteration,
                                        data_handle._decision_iteration)
         model.before_model_run(model_data_handle)
Exemplo n.º 8
0
    def test_set_data_with_square_brackets(self, mock_store, mock_model):
        """should allow dict-like write access to output data
        """
        expected = np.array([[1.0]])
        data_handle = DataHandle(mock_store, 1, 2015, [2015, 2020], mock_model)

        data_handle["test"] = expected
        assert data_handle["test"] == expected

        mock_store.write_results.assert_called_with(1, 'test_model', 'test',
                                                    expected, 'test_regions',
                                                    'test_intervals', 2015,
                                                    None, None)
Exemplo n.º 9
0
    def test_get_data(self, mock_store, mock_model):
        """should allow read access to input data
        """
        data_handle = DataHandle(mock_store, 1, 2015, [2015, 2020], mock_model)
        expected = np.array([[1.0]])
        actual = data_handle.get_data("test")
        assert actual == expected

        mock_store.read_results.assert_called_with(
            1,
            'test_source',  # read from source model
            'test_output',  # using source model output name
            'test_regions',
            'test_intervals',
            2015,
            None,
            None)
Exemplo n.º 10
0
    def test_get_data_with_conversion(self, mock_store,
                                      mock_model_with_conversion):
        """should convert liters to milliliters (1 -> 0.001)
        """
        data_handle = DataHandle(mock_store, 1, 2015, [2015, 2020],
                                 mock_model_with_conversion)
        expected = np.array([[0.001]])
        actual = data_handle.get_data("test")
        assert actual == expected

        mock_store.read_results.assert_called_with(
            1,
            'test_source',  # read from source model
            'test_output',  # using source model output name
            'test_regions',
            'test_intervals',
            2015,
            None,
            None)
Exemplo n.º 11
0
def get_data_handle(model):
    """Return a data handle for the model
    """
    store = MemoryInterface()
    store.write_sos_model_run({
        'name': 'test',
        'narratives': {}
    })
    store.write_scenario_data(
        'Arbitrary Demand Scenario',
        'electricity_demand_output',
        np.array([[123]]),
        'LSOA',
        'annual',
        2010)
    return DataHandle(
        store,
        'test',  # modelrun_name
        2010,  # current_timestep
        [2010],  # timesteps
        model
    )
Exemplo n.º 12
0
    def _run_iteration(self, i, data_handle):
        """Run all models within the set

        Arguments
        ---------
        i : int
            Iteration counter
        data_handle : smif.data_layer.DataHandle
        """
        for model in self.models.values():
            self.logger.info("Simulating %s, iteration %s", model.name, i)
            model_data_handle = DataHandle(data_handle._store,
                                           data_handle._modelrun_name,
                                           data_handle._current_timestep,
                                           data_handle._timesteps, model, i,
                                           data_handle._decision_iteration)
            # Start by running all models in set with best guess
            # - zeroes
            # - last year's inputs
            if i == 0:
                self._guess_results(model, model_data_handle)
            else:
                model.simulate(model_data_handle)
Exemplo n.º 13
0
    def _converged(self, data_handle):
        """Check whether the results of a set of models have converged.

        Returns
        -------
        converged: bool
            True if the results have converged to within a tolerance

        Raises
        ------
        DiverganceError
            If the results appear to be diverging
        """
        if self._current_iteration < 2:
            # must have at least two result sets per model to assess convergence
            return False

        # each data output is a dict with
        #   str key (parameter name) =>
        #       np.ndarray value (regions x intervals)
        converged = []
        for model in self.models.values():
            model_data_handle = DataHandle(data_handle._store,
                                           data_handle._modelrun_name,
                                           data_handle._current_timestep,
                                           data_handle._timesteps, model,
                                           self._current_iteration,
                                           data_handle._decision_iteration)
            converged.append(self._model_converged(model, model_data_handle))

        if all(converged):
            # if all most recent are almost equal to penultimate, must have converged
            return True

        # TODO check for divergence and raise error

        return False
Exemplo n.º 14
0
 def test_create(self):
     """should be created with a DataInterface
     """
     DataHandle(Mock(), 1, 2015, [2015, 2020], Mock())
Exemplo n.º 15
0
 def test_previous_timestep(self):
     """should return previous timestep from list
     """
     data_handle = DataHandle(Mock(), 1, 2020, [2015, 2020], Mock())
     assert data_handle.previous_timestep == 2015
Exemplo n.º 16
0
 def test_base_timestep(self):
     """should return first timestep in list
     """
     data_handle = DataHandle(Mock(), 1, 2015, [2015, 2020], Mock())
     assert data_handle.base_timestep == 2015
Exemplo n.º 17
0
 def test_current_timestep(self):
     """should return current timestep
     """
     data_handle = DataHandle(Mock(), 1, 2015, [2015, 2020], Mock())
     assert data_handle.current_timestep == 2015