コード例 #1
0
ファイル: grid.py プロジェクト: NREL/HOPP
    def __init__(self, site: SiteInfo, interconnect_kw):
        """
        Class that houses the hybrid system performance and financials. Enforces interconnection and curtailment
        limits based on PySAM's Grid module

        :param site: Power source site information (SiteInfo object)
        :param interconnect_kw: Interconnection limit [kW]
        """
        system_model = GridModel.default("GenericSystemSingleOwner")

        financial_model: Singleowner.Singleowner = Singleowner.from_existing(system_model,
                                                                             "GenericSystemSingleOwner")
        super().__init__("Grid", site, system_model, financial_model)

        self._system_model.GridLimits.enable_interconnection_limit = 1
        self._system_model.GridLimits.grid_interconnection_limit_kwac = interconnect_kw

        # financial calculations set up
        self._financial_model.value("add_om_num_types", 1)

        self._dispatch: GridDispatch = None

        # TODO: figure out if this is the best place for these
        self.missed_load = [0.]
        self.missed_load_percentage = 0.0
        self.schedule_curtailed = [0.]
        self.schedule_curtailed_percentage = 0.0
コード例 #2
0
    def __init__(self,
                 site: SiteInfo,
                 battery_config: dict,
                 chemistry: str = 'lfpgraphite',
                 system_voltage_volts: float = 500):
        """
        Battery Storage class based on PySAM's BatteryStateful Model

        :param site: Power source site information (SiteInfo object)
        :param battery_config: Battery configuration with the following keys:

            #. ``system_capacity_kwh``: float, Battery energy capacity [kWh]
            #. ``system_capacity_kw``: float, Battery rated power capacity [kW]

        :param chemistry: Battery storage chemistry, options include:

            #. ``LFPGraphite``: Lithium Iron Phosphate (Lithium Ion)
            #. ``LMOLTO``: LMO/Lithium Titanate (Lithium Ion)
            #. ``LeadAcid``: Lead Acid
            #. ``NMCGraphite``: Nickel Manganese Cobalt Oxide (Lithium Ion)

        :param system_voltage_volts: Battery system voltage [VDC]
        """
        for key in ('system_capacity_kwh', 'system_capacity_kw'):
            if key not in battery_config.keys():
                raise ValueError

        system_model = BatteryModel.default(chemistry)
        financial_model = Singleowner.from_existing(system_model, "StandaloneBatterySingleOwner")
        super().__init__("Battery", site, system_model, financial_model)

        self.Outputs = BatteryOutputs(n_timesteps=site.n_timesteps)
        self.system_capacity_kw: float = battery_config['system_capacity_kw']
        self.chemistry = chemistry
        BatteryTools.battery_model_sizing(self._system_model,
                                          battery_config['system_capacity_kw'],
                                          battery_config['system_capacity_kwh'],
                                          system_voltage_volts,
                                          module_specs=Battery.module_specs)
        self._system_model.ParamsPack.h = 20
        self._system_model.ParamsPack.Cp = 900
        self._system_model.ParamsCell.resistance = 0.001
        self._system_model.ParamsCell.C_rate = battery_config['system_capacity_kw'] / battery_config['system_capacity_kwh']

        # Minimum set of parameters to set to get statefulBattery to work
        self._system_model.value("control_mode", 0.0)
        self._system_model.value("input_current", 0.0)
        self._system_model.value("dt_hr", 1.0)
        self._system_model.value("minimum_SOC", 10.0)
        self._system_model.value("maximum_SOC", 90.0)
        self._system_model.value("initial_SOC", 10.0)

        self._dispatch = None

        logger.info("Initialized battery with parameters and state {}".format(self._system_model.export()))
コード例 #3
0
ファイル: pv_source.py プロジェクト: NREL/HOPP
    def __init__(self,
                 site: SiteInfo,
                 pv_config: dict,
                 detailed_not_simple: bool = False):
        """

        :param pv_config: dict, with keys ('system_capacity_kw', 'layout_params')
            where 'layout_params' is of the SolarGridParameters type
        :param detailed_not_simple:
            Detailed model uses Pvsamv1, simple uses PVWatts
        """
        if 'system_capacity_kw' not in pv_config.keys():
            raise ValueError

        self._detailed_not_simple: bool = detailed_not_simple

        if not detailed_not_simple:
            system_model = Pvwatts.default("PVWattsSingleOwner")
            financial_model = Singleowner.from_existing(system_model, "PVWattsSingleOwner")
        else:
            system_model = Pvsam.default("FlatPlatePVSingleOwner")
            financial_model = Singleowner.from_existing(system_model, "FlatPlatePVSingleOwner")

        super().__init__("SolarPlant", site, system_model, financial_model)

        self._system_model.SolarResource.solar_resource_data = self.site.solar_resource.data

        self.dc_degradation = [0]

        params: Optional[PVGridParameters] = None
        if 'layout_params' in pv_config.keys():
            params: PVGridParameters = pv_config['layout_params']
        self._layout = PVLayout(site, system_model, params)

        self._dispatch: PvDispatch = None

        self.system_capacity_kw: float = pv_config['system_capacity_kw']
コード例 #4
0
Most recently tested against PySAM 2.2.3

@author: frohro
"""
import json
import PySAM.GenericSystem as GenericSystem
import PySAM.Grid as Grid
import PySAM.Singleowner as Singleowner
import PySAM.PySSC as pssc

ssc = pssc.PySSC()
with open("Examples/100mW_Generic.json") as f:
    dic = json.load(f)
    gs_dat = pssc.dict_to_ssc_table(dic, "generic_system")
    grid_dat = pssc.dict_to_ssc_table(dic, "grid")
    so_dat = pssc.dict_to_ssc_table(dic, "singleowner")

    gs = GenericSystem.wrap(gs_dat)
    grid = Grid.from_existing(gs)
    grid.assign(Grid.wrap(grid_dat).export())

    # to create GenericSystem and Singleowner combined simulation, sharing the same data
    so = Singleowner.from_existing(gs)
    so.assign(Singleowner.wrap(so_dat).export())

gs.execute()
grid.execute()
so.execute()
print('Made it past execute.')
print(gs.Outputs.export())  # as dictionary
コード例 #5
0
import PySAM.ResourceTools as tools
import PySAM.Windpower as wp
import PySAM.Singleowner as so
    
# --- Initialize Wind Fetcher ---
wtkfetcher = tools.FetchResourceFiles(
                tech='wind',
                workers=1, #thread workers if fetching multiple files
                nrel_api_key=<NREL_API_KEY>,
                nrel_api_email=<NREL_API_EMAIL>)

# --- Pass a list of (lon, lat) tuples or Shapely points to fetch the nearest resource data ---
lon_lats = [(-105.1800775, 39.7383155)]  # golden CO
wtkfetcher.fetch(lon_lats)
    
# --- Get resource data file path ---
wtk_path_dict = wtkfetcher.resource_file_paths_dict
wtk_fp = wtk_path_dict[lon_lats[0]]

# --- Initialize Generator ---
generator = wp.default('WindPowerSingleOwner')
generator.Resource.assign({'wind_resource_model_choice': 0})
generator.Resource.assign({'wind_resource_filename': wtk_fp}) #pass path to resource file

# --- Initialize Financial Model ---
financial = so.from_existing(generator, "WindPowerSingleOwner")

# --- Execute Models ---
generator.execute()
financial.execute()
コード例 #6
0
    def __init__(
            self,
            site: SiteInfo,
            farm_config: dict,
            rating_range_kw: tuple = (1000, 3000),
    ):
        """
        Set up a WindPlant

        :param farm_config: dict, with keys ('num_turbines', 'turbine_rating_kw', 'rotor_diameter', 'hub_height', 'layout_mode', 'layout_params')
            where layout_mode can be selected from the following:
            - 'boundarygrid': regular grid with boundary turbines, requires WindBoundaryGridParameters as 'params'
            - 'grid': regular grid with dx, dy distance, 0 angle; does not require 'params'

        :param rating_range_kw:
            allowable kw range of turbines, default is 1000 - 3000 kW
        """
        self._rating_range_kw = rating_range_kw

        if 'model_name' in farm_config.keys():
            if farm_config['model_name'] == 'floris':
                print('FLORIS is the system model...')
                system_model = Floris(farm_config,
                                      site,
                                      timestep=farm_config['timestep'])
                financial_model = Singleowner.default("WindPowerSingleOwner")
            else:
                raise NotImplementedError
        else:
            system_model = Windpower.default("WindPowerSingleOwner")
            financial_model = Singleowner.from_existing(
                system_model, "WindPowerSingleOwner")

        super().__init__("WindPlant", site, system_model, financial_model)
        self._system_model.value("wind_resource_data",
                                 self.site.wind_resource.data)

        if 'layout_mode' not in farm_config.keys():
            layout_mode = 'grid'
        else:
            layout_mode = farm_config['layout_mode']

        params: Optional[WindBoundaryGridParameters] = None
        if layout_mode == 'boundarygrid':
            if 'layout_params' not in farm_config.keys():
                raise ValueError(
                    "Parameters of WindBoundaryGridParameters required for boundarygrid layout mode"
                )
            else:
                params: WindBoundaryGridParameters = farm_config[
                    'layout_params']

        self._layout = WindLayout(site, system_model, layout_mode, params)

        self._dispatch: WindDispatch = None

        if 'turbine_rating_kw' not in farm_config.keys():
            raise ValueError("Turbine rating required for WindPlant")

        if 'num_turbines' not in farm_config.keys():
            raise ValueError("Num Turbines required for WindPlant")

        self.turb_rating = farm_config['turbine_rating_kw']
        self.num_turbines = farm_config['num_turbines']
        if 'hub_height' in farm_config.keys():
            self._system_model.Turbine.wind_turbine_hub_ht = farm_config[
                'hub_height']
        if 'rotor_diameter' in farm_config.keys():
            self.rotor_diameter = farm_config['rotor_diameter']
コード例 #7
0
# --- List of (lon, lat) tuples or Shapely points ---
lon_lats = [(lon, lat)]
wtkfetcher.fetch(lon_lats)

# --- Get resource data file path ---
wtk_path_dict = wtkfetcher.resource_file_paths_dict
wtk_fp = wtk_path_dict[lon_lats[0]]

# --- Initialize generator ---
if wtk_fp is not None:
    generator = wp.default('WindPowerSingleOwner')
    generator.Resource.assign({'wind_resource_model_choice': 0})
    generator.Resource.assign({'wind_resource_filename': wtk_fp})

    # --- Initialize financial model ---
    financial = so.from_existing(generator, 'WindPowerSingleOwner')

    print('Wind Power - Single Owner Results')
    generator.execute()
    print('capacity factor = {:.3f}'.format(generator.Outputs.capacity_factor))
    financial.execute()
    print('npv = ${:,.2f}'.format(
        financial.Outputs.project_return_aftertax_npv))

else:
    print('Wind resource file does not exist. Skipping wind model simulation.')

# --- Solar Example ---

# --- Initialize Solar Resource Fetcher with minimum parameters ---
# See function documentation for full parameter list