From fd760e6c037bcbe218c1f9a58437f6ebb15a63d5 Mon Sep 17 00:00:00 2001 From: Rahul Kakodkar Date: Thu, 17 Aug 2023 16:30:44 -0500 Subject: [PATCH 1/3] introduced Results type object --- src/energiapy/components/case_study.py | 20 +++++++++++++++----- src/energiapy/components/result.py | 12 ++++++++++++ 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/energiapy/components/case_study.py b/src/energiapy/components/case_study.py index 0b7e4eb7..5d944c58 100644 --- a/src/energiapy/components/case_study.py +++ b/src/energiapy/components/case_study.py @@ -13,17 +13,19 @@ from dataclasses import dataclass from typing import Union, Set, Dict, Tuple import copy +from warnings import warn + from ..components.scenario import Scenario from ..components.process import Process from ..components.resource import Resource from ..components.location import Location -from ..components.result import Result +from ..components.result import Result, Results from ..model.formulate import formulate as formulate_casestudy from ..model.solve import solve as solve_casestudy from ..model.formulate import Objective, ModelClass from ..model.constraints.constraints import Constraints -from pyomo.environ import ConcreteModel, Suffix +from pyomo.environ import ConcreteModel @dataclass @@ -35,12 +37,16 @@ class CaseStudy: scenarios: Can be a list of scenarios generated apriori or a single scenario that you want to vary vary (str, optional): if single scenario, what needs to be varied. e.g. demand. Defaults to None vary_as (str, optional): what values to assign while varying. Should be a list of values to take. Defaults to None + formulations_dict (dict, optional): dictionary with pyomo instances. Defaults to None + results_dict (Results, optional): Results type object, has multiple Result objects embedded. Defaults to None """ name: str scenarios: Union[list, Scenario] vary: str = None vary_as: list = None + formulations_dict: dict = None + results_dict: Results = None def __post_init__(self): @@ -99,11 +105,15 @@ def solve(self, solver: str, interface: str = 'pyomo', saveformat: str = None, p Returns: Result: result type object """ + if self.formulations_dict is None: + warn('Instances have not been formulated yet, use .formulate() first') + instances = list(self.formulations_dict.values()) names = list(self.formulations_dict.keys()) - self.results_dict = {names[i]: solve_casestudy(instance=instances[i], scenario=self.scenarios[i], - solver=solver, name=names[i], interface=interface, saveformat=saveformat, - print_solversteps=print_solversteps, log=log) for i in range(len(names))} + self.results_dict = Results(name=self.name + '_results', results={names[i]: solve_casestudy(instance=instances[i], scenario=self.scenarios[i], + solver=solver, name=names[ + i], interface=interface, saveformat=saveformat, + print_solversteps=print_solversteps, log=log) for i in range(len(names))}) return self.results_dict diff --git a/src/energiapy/components/result.py b/src/energiapy/components/result.py index 36062ab4..04372e19 100644 --- a/src/energiapy/components/result.py +++ b/src/energiapy/components/result.py @@ -13,6 +13,7 @@ import json import pickle from dataclasses import dataclass +from typing import Dict @dataclass @@ -145,3 +146,14 @@ def __hash__(self): def __eq__(self, other): return self.name == other.name + + +@dataclass +class Results: + """Contains multiple Result objects + Args: + name: name of the results object, inherits from CaseStudy + results: dictionary of Result objects. + """ + name: str + results: Dict[str, Result] From dd5acdeb5e51eadf7855b603eeb09e87a83f7ae3 Mon Sep 17 00:00:00 2001 From: Rahul Kakodkar Date: Fri, 18 Aug 2023 09:03:20 -0500 Subject: [PATCH 2/3] location level plotting functions --- src/energiapy/plot/plot_scenario.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/energiapy/plot/plot_scenario.py b/src/energiapy/plot/plot_scenario.py index 9919f0af..a8162a69 100644 --- a/src/energiapy/plot/plot_scenario.py +++ b/src/energiapy/plot/plot_scenario.py @@ -1,4 +1,4 @@ -"""plotting module +"""plotting module for scenarios """ __author__ = "Rahul Kakodkar" From d6b2d025a0bcf89b69c07642d9769b91de87348c Mon Sep 17 00:00:00 2001 From: Rahul Kakodkar Date: Fri, 18 Aug 2023 09:03:48 -0500 Subject: [PATCH 3/3] file for location level plotting --- src/energiapy/plot/plot_location.py | 248 ++++++++++++++++++++++++++++ 1 file changed, 248 insertions(+) create mode 100644 src/energiapy/plot/plot_location.py diff --git a/src/energiapy/plot/plot_location.py b/src/energiapy/plot/plot_location.py new file mode 100644 index 00000000..aab9fa59 --- /dev/null +++ b/src/energiapy/plot/plot_location.py @@ -0,0 +1,248 @@ +"""plotting module for location +""" + +__author__ = "Rahul Kakodkar" +__copyright__ = "Copyright 2023, Multi-parametric Optimization & Control Lab" +__credits__ = ["Rahul Kakodkar", "Efstratios N. Pistikopoulos"] +__license__ = "MIT" +__version__ = "1.0.8" +__maintainer__ = "Rahul Kakodkar" +__email__ = "cacodcar@tamu.edu" +__status__ = "Production" + +import matplotlib.pyplot as plt +from matplotlib import rc + +from ..components.location import Location +from ..components.process import Process +from ..components.resource import Resource +from ..components.case_study import CaseStudy +from ..components.scenario import Scenario +from ..utils.plot_utils import axis_formatter + + +def capacity_factor(location: Location, process: Process, fig_size: tuple = (12, 6), font_size: int = 16, color: str = 'blue', usetex: bool = False): + """generates a plot for varying capacity factor of process + + Args: + process (Process): process energiapy object + location (Location): location energiapy object + font_size (int, optional): font size. Defaults to 16. + fig_size (tuple, optional): figure size. Defaults to (12,6). + color (str, optional): color of plot. Defaults to 'blue'. + usetex (bool, optional): False, if using latex font, need Tex set up (prone to errors). Defaults to 'False'. + """ + + rc('font', **{'family': 'serif', + 'serif': ['Computer Modern'], 'size': font_size}) + rc('text', usetex=False) + fig, ax = plt.subplots(figsize=fig_size) + y_ = list(location.capacity_factor[process.name].values()) + x_ = list(range(len(y_))) + ax.plot(x_, y_, linewidth=0.5, color=color) + ax = axis_formatter(axes=ax, xcord=x_, axis_labels='M') + plt.title(f'Conversion factor for {process.label} in {location.label}') + plt.ylabel("Normalized capacity factor") + plt.xlabel("Scheduling Horizon") + plt.grid(alpha=0.3) + plt.rcdefaults() + return + + +def price_factor(resource: Resource, location: Location, fig_size: tuple = (12, 6), font_size: int = 16, color: str = 'blue', usetex: bool = False): + """generates a plot for varying price factor for purchase of resource + + Args: + resource (Resource): resource energiapy object + location (Location): location energiapy object + font_size (int, optional): font size. Defaults to 16. + fig_size (tuple, optional): figure size. Defaults to (12,6). + color (str, optional): color of plot. Defaults to 'blue'. + usetex (bool, optional): False, if using latex font, need Tex set up (prone to errors). Defaults to 'False'. + """ + rc('font', **{'family': 'serif', + 'serif': ['Computer Modern'], 'size': font_size}) + rc('text', usetex=False) + fig, ax = plt.subplots(figsize=fig_size) + y_ = list(location.price_factor[resource.name].values()) + x_ = list(range(len(y_))) + ax.plot(x_, y_, linewidth=0.5, color=color) + ax = axis_formatter(axes=ax, xcord=x_, axis_labels='M') + plt.title(f'Price factor for {resource.label} in {location.label}') + plt.ylabel("Normalized cost factor") + plt.xlabel("Scheduling Horizon") + plt.grid(alpha=0.3) + plt.rcdefaults() + return + + +def demand_factor(resource: Resource, location: Location, + fig_size: tuple = (12, 6), font_size: int = 16, color: str = 'blue', usetex: bool = False): + """generates a plot for varying demand factor of resource + + Args: + resource (Resource): resource energiapy object + location (Location): location energiapy object + font_size (int, optional): font size. Defaults to 16. + fig_size (tuple, optional): figure size. Defaults to (12,6). + color (str, optional): color of plot. Defaults to 'blue'. + usetex (bool, optional): False, if using latex font, need Tex set up (prone to errors). Defaults to 'False'. + """ + rc('font', **{'family': 'serif', + 'serif': ['Computer Modern'], 'size': font_size}) + rc('text', usetex=False) + fig, ax = plt.subplots(figsize=fig_size) + y_ = list(location.demand_factor[resource.name].values()) + x_ = list(range(len(y_))) + ax.plot(x_, y_, linewidth=0.5, color=color) + ax = axis_formatter(axes=ax, xcord=x_, axis_labels='M') + plt.title(f'Demand factor for {resource.label} in {location.label}') + plt.ylabel("Normalized demand factor") + plt.xlabel("Scheduling Horizon") + plt.grid(alpha=0.3) + plt.rcdefaults() + return + + +def capex_factor(process: Process, location: Location, + fig_size: tuple = (12, 6), font_size: int = 16, color: str = 'blue'): + """generates a plot for varying technology capital expenditure + + Args: + process (Process): process energiapy object + location (Location): location energiapy object + font_size (int, optional): font size. Defaults to 16. + fig_size (tuple, optional): figure size. Defaults to (12,6). + color (str, optional): color of plot. Defaults to 'blue'. + usetex (bool, optional): False, if using latex font, need Tex set up (prone to errors). Defaults to 'False'. + """ + rc('font', **{'family': 'serif', + 'serif': ['Computer Modern'], 'size': font_size}) + rc('text', usetex=False) + fig, ax = plt.subplots(figsize=fig_size) + y_ = list(location.capex_factor[process.name].values()) + x_ = list(range(len(y_))) + ax.plot(x_, y_, linewidth=0.5, color=color) + ax = axis_formatter(axes=ax, xcord=x_, axis_labels='M') + plt.title(f'Capex factor for {process.label} in {location.label}') + plt.ylabel("Normalized capex factor") + plt.xlabel("Scheduling Horizon") + plt.grid(alpha=0.3) + plt.rcdefaults() + return + + +def vopex_factor(process: Process, location: Location, + fig_size: tuple = (12, 6), font_size: int = 16, color: str = 'blue'): + """generates a plot for varying technology variable operational expenditure + + Args: + process (Process): process energiapy object + location (Location): location energiapy object + font_size (int, optional): font size. Defaults to 16. + fig_size (tuple, optional): figure size. Defaults to (12,6). + color (str, optional): color of plot. Defaults to 'blue'. + usetex (bool, optional): False, if using latex font, need Tex set up (prone to errors). Defaults to 'False'. + """ + rc('font', **{'family': 'serif', + 'serif': ['Computer Modern'], 'size': font_size}) + rc('text', usetex=False) + fig, ax = plt.subplots(figsize=fig_size) + y_ = list(location.vopex_factor[process.name].values()) + x_ = list(range(len(y_))) + ax.plot(x_, y_, linewidth=0.5, color=color) + ax = axis_formatter(axes=ax, xcord=x_, axis_labels='M') + plt.title(f'Vopex factor for {process.label} in {location.label}') + plt.ylabel("Normalized vopex factor") + plt.xlabel("Scheduling Horizon") + plt.grid(alpha=0.3) + plt.rcdefaults() + return + + +def fopex_factor(process: Process, location: Location, + fig_size: tuple = (12, 6), font_size: int = 16, color: str = 'blue'): + """generates a plot for varying technology fixed operational expenditure + + Args: + process (Process): process energiapy object + location (Location): location energiapy object + font_size (int, optional): font size. Defaults to 16. + fig_size (tuple, optional): figure size. Defaults to (12,6). + color (str, optional): color of plot. Defaults to 'blue'. + usetex (bool, optional): False, if using latex font, need Tex set up (prone to errors). Defaults to 'False'. + """ + rc('font', **{'family': 'serif', + 'serif': ['Computer Modern'], 'size': font_size}) + rc('text', usetex=False) + fig, ax = plt.subplots(figsize=fig_size) + y_ = list(location.fopex_factor[process.name].values()) + x_ = list(range(len(y_))) + ax.plot(x_, y_, linewidth=0.5, color=color) + ax = axis_formatter(axes=ax, xcord=x_, axis_labels='M') + plt.title(f'Fopex factor for {process.label} in {location.label}') + plt.ylabel("Normalized fopex factor") + plt.xlabel("Scheduling Horizon") + plt.grid(alpha=0.3) + plt.rcdefaults() + return + + +def availability_factor(resource: Resource, location: Location, + fig_size: tuple = (12, 6), font_size: int = 16, color: str = 'blue', usetex: bool = False): + """generates a plot for varying availability factor of resource + + Args: + + resource (Resource): resource energiapy object + location (Location): location energiapy object + font_size (int, optional): font size. Defaults to 16. + fig_size (tuple, optional): figure size. Defaults to (12,6). + color (str, optional): color of plot. Defaults to 'blue'. + usetex (bool, optional): False, if using latex font, need Tex set up (prone to errors). Defaults to 'False'. + """ + rc('font', **{'family': 'serif', + 'serif': ['Computer Modern'], 'size': font_size}) + rc('text', usetex=False) + fig, ax = plt.subplots(figsize=fig_size) + y_ = list( + location.availability_factor[resource.name].values()) + x_ = list(range(len(y_))) + ax.plot(x_, y_, linewidth=0.5, color=color) + ax = axis_formatter(axes=ax, xcord=x_, axis_labels='M') + plt.title(f'Demand factor for {resource.label} in {location.label}') + plt.ylabel("Normalized availability factor") + plt.xlabel("Scheduling Horizon") + plt.grid(alpha=0.3) + plt.rcdefaults() + return + + +def revenue_factor(resource: Resource, location: Location, + fig_size: tuple = (12, 6), font_size: int = 16, color: str = 'blue', usetex: bool = False): + """generates a plot for varying revenue factor of resource + + Args: + + resource (Resource): resource energiapy object + location (Location): location energiapy object + font_size (int, optional): font size. Defaults to 16. + fig_size (tuple, optional): figure size. Defaults to (12,6). + color (str, optional): color of plot. Defaults to 'blue'. + usetex (bool, optional): False, if using latex font, need Tex set up (prone to errors). Defaults to 'False'. + """ + rc('font', **{'family': 'serif', + 'serif': ['Computer Modern'], 'size': font_size}) + rc('text', usetex=False) + fig, ax = plt.subplots(figsize=fig_size) + y_ = list( + location.revenue_factor[resource.name].values()) + x_ = list(range(len(y_))) + ax.plot(x_, y_, linewidth=0.5, color=color) + ax = axis_formatter(axes=ax, xcord=x_, axis_labels='M') + plt.title(f'Demand factor for {resource.label} in {location.label}') + plt.ylabel("Normalized revenue factor") + plt.xlabel("Scheduling Horizon") + plt.grid(alpha=0.3) + plt.rcdefaults() + return