def run(self, force_rerun=False, **kwargs): """ Run the model. If ``force_rerun`` is True, any existing results will be overwritten. Additional kwargs are passed to the backend. """ # Check that results exist and are non-empty if hasattr(self, 'results') and self.results.data_vars and not force_rerun: raise exceptions.ModelError( 'This model object already has results. ' 'Use model.run(force_rerun=True) to force' 'the results to be overwritten with a new run.' ) if (self._model_data.attrs['run.mode'] == 'operate' and not self._model_data.attrs['allow_operate_mode']): raise exceptions.ModelError( 'Unable to run this model in operational mode, probably because ' 'there exist non-uniform timesteps (e.g. from time masking)' ) results, self._backend_model, interface = run_backend( self._model_data, self._timings, **kwargs ) # Add additional post-processed result variables to results if results.attrs.get('termination_condition', None) == 'optimal': results = postprocess.postprocess_model_results( results, self._model_data, self._timings ) for var in results.data_vars: results[var].attrs['is_result'] = 1 self._model_data.update(results) self._model_data.attrs.update(results.attrs) if 'run_solution_returned' in self._timings.keys(): self._model_data.attrs['solution_time'] = ( self._timings['run_solution_returned'] - self._timings['run_start']).total_seconds() self._model_data.attrs['time_finished'] = ( self._timings['run_solution_returned'].strftime('%Y-%m-%d %H:%M:%S') ) self.results = self._model_data.filter_by_attrs(is_result=1) self.backend = interface(self)
def run(self, force_rerun=False, **kwargs): """ Run the model. If ``force_rerun`` is True, any existing results will be overwritten. Additional kwargs are passed to the backend. """ # Check that results exist and are non-empty if hasattr(self, 'results') and self.results.data_vars and not force_rerun: raise exceptions.ModelError( 'This model object already has results. ' 'Use model.run(force_rerun=True) to force' 'the results to be overwritten with a new run.') if (self._model_data.attrs['run.mode'] == 'operate' and not self._model_data.attrs['allow_operate_mode']): raise exceptions.ModelError( 'Unable to run this model in operational mode, probably because ' 'there exist non-uniform timesteps (e.g. from time masking)') results, self._backend_model, interface = run_backend( self._model_data, self._timings, **kwargs) # Add additional post-processed result variables to results if results.attrs.get('termination_condition', None) == 'optimal': results = postprocess.postprocess_model_results( results, self._model_data, self._timings) for var in results.data_vars: results[var].attrs['is_result'] = 1 self._model_data.update(results) self._model_data.attrs.update(results.attrs) if 'run_solution_returned' in self._timings.keys(): self._model_data.attrs['solution_time'] = ( self._timings['run_solution_returned'] - self._timings['run_start']).total_seconds() self._model_data.attrs['time_finished'] = ( self._timings['run_solution_returned'].strftime( '%Y-%m-%d %H:%M:%S')) self.results = self._model_data.filter_by_attrs(is_result=1) self.backend = interface(self)
def rerun_pyomo_model(model_data, backend_model): """ Rerun the Pyomo backend, perhaps after updating a parameter value, (de)activating a constraint/objective or updating run options in the model model_data object (e.g. `run.solver`). Returns ------- new_model : calliope.Model New calliope model, including both inputs and results, but no backend interface. """ backend_model.__calliope_run_config = AttrDict.from_yaml_string( model_data.attrs['run_config']) if backend_model.__calliope_run_config['mode'] != 'plan': raise exceptions.ModelError( 'Cannot rerun the backend in {} run mode. Only `plan` mode is ' 'possible.'.format(backend_model.__calliope_run_config['mode'])) timings = {} log_time(logger, timings, 'model_creation') results, backend_model = backend_run.run_plan(model_data, timings, run_pyomo, build_only=False, backend_rerun=backend_model) inputs = access_pyomo_model_inputs(backend_model) # Add additional post-processed result variables to results if results.attrs.get('termination_condition', None) in ['optimal', 'feasible']: results = postprocess_model_results(results, model_data.reindex(results.coords), timings) for key, var in results.data_vars.items(): var.attrs['is_result'] = 1 for key, var in inputs.data_vars.items(): var.attrs['is_result'] = 0 new_model_data = xr.merge((results, inputs)) new_model_data.attrs.update(model_data.attrs) # Only add coordinates from the original model_data that don't already exist new_coords = [ i for i in model_data.coords.keys() if i not in new_model_data.coords.keys() ] new_model_data = new_model_data.update(model_data[new_coords]) # Reorganise the coordinates so that model data and new model data share # the same order of items in each dimension new_model_data = new_model_data.reindex(model_data.coords) exceptions.warn( 'The results of rerunning the backend model are only available within ' 'the Calliope model returned by this function call.') new_calliope_model = calliope.Model(config=None, model_data=new_model_data) new_calliope_model._timings = timings return new_calliope_model