Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updates to install requirements.txt and multiple files for NASA POWER API integration #27

Closed
wants to merge 20 commits into from
Closed
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
9e5592d
Updating multiple HOPP files to resolve developer install error and N…
dakotaramos Apr 18, 2022
82a4a6b
Merge branch 'master' of https://github.com/NREL/HOPP
dakotaramos Apr 18, 2022
d3461b4
updating flatirons site lat/lon/elev and corresponding test files
dakotaramos Apr 20, 2022
22d8dae
removing inline comments in files from last commit
dakotaramos Apr 20, 2022
23ecb97
updating test files with new logic and values
dakotaramos Apr 22, 2022
798351e
work in progress
dakotaramos May 5, 2022
a929a60
2nd try
dakotaramos May 5, 2022
32e9e96
updating nrel api V2
dakotaramos May 5, 2022
31b8d12
updated testing values based on latest pull of HOPP main and correcte…
dakotaramos May 5, 2022
870f3ec
removing extra commented lines
dakotaramos May 5, 2022
2ca5d18
removing conversion of np.array to list from HOPP, added to PySAM/Res…
dakotaramos May 6, 2022
686e032
restoring previous data.setter logic in wind_resource.py given post p…
dakotaramos May 6, 2022
748d523
updating site_info.py to allow specification of turbine_hub_ht as an …
dakotaramos May 10, 2022
36259f2
updating site_info.py and wind_source.py to match future merge https:…
dakotaramos May 11, 2022
90ed8a6
correcting spelling error of rotor diameter in wind_source.py
dakotaramos May 11, 2022
f2c511a
remote amarillo site
dguittet May 20, 2022
294406e
remove changes to tests
dguittet May 20, 2022
5d27f48
rename vegtype to nasa_vegtype
dguittet May 20, 2022
5d07616
minor change to simulate_hybrid
dguittet May 20, 2022
4cf81df
add test
dguittet May 20, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions examples/simulate_hybrid.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,15 @@
},
'wind': {
'num_turbines': 10,
'turbine_rating_kw': 2000
'turbine_rating_kw': 2000,
'hub_height': 80
}}

# Get resource
lat = flatirons_site['lat']
lon = flatirons_site['lon']
prices_file = examples_dir.parent / "resource_files" / "grid" / "pricing-data-2015-IronMtn-002_factors.csv"
site = SiteInfo(flatirons_site, grid_resource_file=prices_file)
site = SiteInfo(flatirons_site, grid_resource_file=prices_file, api='nrel', hub_height=80)

# Create model
hybrid_plant = HybridSimulation(technologies, site, interconnect_kw=interconnection_size_mw * 1000)
Expand Down
8 changes: 7 additions & 1 deletion hybrid/resource/resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import json
import requests
import time
import datetime


class Resource(metaclass=ABCMeta):
Expand All @@ -11,7 +12,7 @@ class Resource(metaclass=ABCMeta):
it is downloaded and saved to 'resource_files' folder. The resource file is then read
to the appropriate SAM resource data format.
"""
def __init__(self, lat, lon, year, **kwargs):
def __init__(self, lat, lon, year, api='nrel', **kwargs):
"""
Parameters
---------
Expand All @@ -21,11 +22,16 @@ def __init__(self, lat, lon, year, **kwargs):
The longitude
year: int
The year of resource_files data
api: string
'nrel' for NREL Developer network APIs or 'nasa' for NASA POWER API
"""

self.latitude = lat
self.longitude = lon
self.year = year
self.start_date = str(datetime.date.min.replace(year=int(self.year))).replace("-","")
self.end_date = str(datetime.date.max.replace(year=int(self.year))).replace("-","")
self.api = api

self.n_timesteps = 8760

Expand Down
27 changes: 21 additions & 6 deletions hybrid/resource/solar_resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,18 @@ class SolarResource(Resource):
Class to manage Solar Resource data
"""

def __init__(self, lat, lon, year, path_resource="", filepath="", **kwargs):
def __init__(self, lat, lon, year, api='nrel', path_resource="", filepath="", **kwargs):
"""

:param lat: float
:param lon: float
:param year: int
:param api : string ('nrel' or 'nasa')
:param path_resource: directory where to save downloaded files
:param filepath: file path of resource file to load
:param kwargs:
"""
super().__init__(lat, lon, year)
super().__init__(lat, lon, year, api)

if os.path.isdir(path_resource):
self.path_resource = path_resource
Expand All @@ -37,9 +38,14 @@ def __init__(self, lat, lon, year, path_resource="", filepath="", **kwargs):

# resource_files files
if filepath == "":
filepath = os.path.join(self.path_resource,
str(lat) + "_" + str(lon) + "_psmv3_" + str(self.interval) + "_" + str(
year) + ".csv")
if self.api == 'nrel':
filepath = os.path.join(self.path_resource,
str(lat) + "_" + str(lon) + "_psmv3_" + str(self.interval) + "_" + str(
year) + ".csv")
elif self.api == 'nasa':
filepath = os.path.join(self.path_resource,
str(lat) + "_" + str(lon) + "_nasa_" + str(self.interval) + "_" + str(
year) + ".csv")
self.filename = filepath

self.check_download_dir()
Expand All @@ -51,13 +57,21 @@ def __init__(self, lat, lon, year, path_resource="", filepath="", **kwargs):

logger.info("SolarResource: {}".format(self.filename))


def download_resource(self):
url = 'https://developer.nrel.gov/api/nsrdb/v2/solar/psm3-download.csv?wkt=POINT({lon}+{lat})&names={year}&leap_day={leap}&interval={interval}&utc={utc}&full_name={name}&email={email}&affiliation={affiliation}&mailing_list={mailing_list}&reason={reason}&api_key={api}&attributes={attr}'.format(
if self.api.lower() == 'nrel':
url = 'https://developer.nrel.gov/api/nsrdb/v2/solar/psm3-download.csv?wkt=POINT({lon}+{lat})&names={year}&leap_day={leap}&interval={interval}&utc={utc}&full_name={name}&email={email}&affiliation={affiliation}&mailing_list={mailing_list}&reason={reason}&api_key={api}&attributes={attr}'.format(
year=self.year, lat=self.latitude, lon=self.longitude, leap=self.leap_year, interval=self.interval,
utc=self.utc, name=self.name, email=self.email,
mailing_list=self.mailing_list, affiliation=self.affiliation, reason=self.reason, api=get_developer_nrel_gov_key(),
attr=self.solar_attributes)

elif self.api.lower() == 'nasa':
url = 'https://power.larc.nasa.gov/api/temporal/hourly/point?start={start}&end={end}&latitude={lat}&longitude={lon}&community=re&parameters=T2M&format=sam&user=TEST'.format(
start=self.start_date, end=self.end_date, lat=self.latitude, lon=self.longitude)
else:
raise NameError(self.api + " does not exist. Try 'nrel' for the NREL developer network NSRDB API or 'nasa' for NASA POWER API")

success = self.call_api(url, filename=self.filename)

return success
Expand Down Expand Up @@ -90,6 +104,7 @@ def data(self, data_dict):
:key wspd: array, wind speed [m/s]
:key tdry: array, dry bulb temp [C]
"""

self._data = SAM_CSV_to_solar_data(data_dict)

def roll_timezone(self, roll_hours, timezone):
Expand Down
39 changes: 29 additions & 10 deletions hybrid/resource/wind_resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,20 @@ class WindResource(Resource):

allowed_hub_height_meters = [10, 40, 60, 80, 100, 120, 140, 160, 200]

def __init__(self, lat, lon, year, wind_turbine_hub_ht, path_resource="", filepath="", **kwargs):
def __init__(self, lat, lon, year, wind_turbine_hub_ht, api='nrel', nasa_vegtype='vegtype_8', path_resource="", filepath="", **kwargs):
"""

:param lat: float
:param lon: float
:param year: int
:param api: string ('nrel' or 'nasa')
:param nasa_vegtype: string (see wind-surface options at https://power.larc.nasa.gov/docs/methodology/meteorology/wind/#corrected-wind-speed)
:param wind_turbine_hub_ht: int
:param path_resource: directory where to save downloaded files
:param filepath: file path of resource file to load
:param kwargs:
"""
super().__init__(lat, lon, year)
super().__init__(lat, lon, year, api)

if os.path.isdir(path_resource):
self.path_resource = path_resource
Expand All @@ -44,6 +46,8 @@ def __init__(self, lat, lon, year, wind_turbine_hub_ht, path_resource="", filepa

self.file_resource_heights = None

self.vegtype = nasa_vegtype

if filepath == "":
self.filename = ""
self.calculate_heights_to_download()
Expand Down Expand Up @@ -78,8 +82,14 @@ def calculate_heights_to_download(self):
heights[0] = height_low
heights.append(height_high)

file_resource_base = os.path.join(self.path_resource, str(self.latitude) + "_" + str(self.longitude) + "_windtoolkit_" + str(
self.year) + "_" + str(self.interval) + "min")
if self.api == 'nrel':
file_resource_base = os.path.join(self.path_resource, str(self.latitude) + "_" + str(self.longitude) + "_windtoolkit_" + str(
self.year) + "_" + str(self.interval) + "min")
elif self.api == 'nasa':
file_resource_base = os.path.join(self.path_resource, str(self.latitude) + "_" + str(self.longitude) + "_nasa_" + str(
self.year) + "_" + str(self.interval) + "min")
else:
raise NameError(self.api + " does not exist. Try 'nrel' for the NREL developer network WindToolkit API or 'nasa' for NASA POWER API")
file_resource_full = file_resource_base
file_resource_heights = dict()

Expand All @@ -98,12 +108,21 @@ def update_height(self, hub_height_meters):
def download_resource(self):
success = os.path.isfile(self.filename)
if not success:
if self.api.lower() == 'nrel':
for height, f in self.file_resource_heights.items():
url = 'https://developer.nrel.gov/api/wind-toolkit/v2/wind/wtk-srw-download?year={year}&lat={lat}&lon={lon}&hubheight={hubheight}&api_key={api_key}&email={email}'.format(
year=self.year, lat=self.latitude, lon=self.longitude, hubheight=height, api_key=get_developer_nrel_gov_key(), email=self.email)

for height, f in self.file_resource_heights.items():
url = 'https://developer.nrel.gov/api/wind-toolkit/v2/wind/wtk-srw-download?year={year}&lat={lat}&lon={lon}&hubheight={hubheight}&api_key={api_key}&email={email}'.format(
year=self.year, lat=self.latitude, lon=self.longitude, hubheight=height, api_key=get_developer_nrel_gov_key(), email=self.email)
success = self.call_api(url, filename=f)

success = self.call_api(url, filename=f)
elif self.api.lower() == 'nasa':
for height, f in self.file_resource_heights.items():
url = 'https://power.larc.nasa.gov/api/temporal/hourly/point?start={start}&end={end}&latitude={lat}&longitude={lon}&community=RE&parameters=T2M&format=srw&wind-surface={surface}&wind-elevation={hubheight}&site-elevation={hubheight}'.format(
start=self.start_date, end=self.end_date, lat=self.latitude, lon=self.longitude, surface=self.vegtype, hubheight=height)

success = self.call_api(url, filename=f)
else:
raise NameError(self.api + " does not exist. Try 'nrel' for the NREL developer network WindToolkit API or 'nasa' for NASA POWER API")

if not success:
raise ValueError('Unable to download wind data')
Expand Down Expand Up @@ -163,5 +182,5 @@ def data(self, data_file):
"""
Sets the wind resource data to a dictionary in SAM Wind format (see Pysam.ResourceTools.SRW_to_wind_data)
"""

self._data = SRW_to_wind_data(data_file)
self._data = SRW_to_wind_data(data_file)
6 changes: 3 additions & 3 deletions hybrid/sites/flatirons_site.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
flatirons_site = {
"lat": 35.2018863,
"lon": -101.945027,
"elev": 1099,
"lat": 39.91,
"lon": -105.22,
"elev": 1800,
dguittet marked this conversation as resolved.
Show resolved Hide resolved
"year": 2012,
"tz": -6,
'site_boundaries': {
Expand Down
10 changes: 6 additions & 4 deletions hybrid/sites/site_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,11 @@ def plot_site(verts, plt_style, labels):

class SiteInfo:

def __init__(self, data, solar_resource_file="", wind_resource_file="", grid_resource_file=""):
def __init__(self, data, solar_resource_file="", wind_resource_file="", grid_resource_file="", api='nrel', nasa_vegtype='vegtype_8', hub_height=80):
set_nrel_key_dot_env()
self.data = data
self.api = api
self.vegtype = nasa_vegtype
self.vertices = np.array([np.array(v) for v in data['site_boundaries']['verts']])
self.polygon: Polygon = Polygon(self.vertices)
self.valid_region = self.polygon.buffer(1e-8)
Expand All @@ -37,10 +39,10 @@ def __init__(self, data, solar_resource_file="", wind_resource_file="", grid_res
self.lon = data['lon']
if 'year' not in data:
data['year'] = 2012
self.solar_resource = SolarResource(data['lat'], data['lon'], data['year'], filepath=solar_resource_file)
self.solar_resource = SolarResource(data['lat'], data['lon'], data['year'], filepath=solar_resource_file, api=self.api)
# TODO: allow hub height to be used as an optimization variable
self.wind_resource = WindResource(data['lat'], data['lon'], data['year'], wind_turbine_hub_ht=80,
filepath=wind_resource_file)
self.wind_resource = WindResource(data['lat'], data['lon'], data['year'], wind_turbine_hub_ht=hub_height,
filepath=wind_resource_file, api=self.api, nasa_vegtype=self.vegtype)
self.elec_prices = ElectricityPrices(data['lat'], data['lon'], data['year'], filepath=grid_resource_file)
self.n_timesteps = len(self.solar_resource.data['gh']) // 8760 * 8760
self.n_periods_per_day = self.n_timesteps // 365 # TODO: Does not handle leap years well
Expand Down
7 changes: 5 additions & 2 deletions hybrid/wind_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def __init__(self,
"""
Set up a WindPlant

:param farm_config: dict, with keys ('num_turbines', 'turbine_rating_kw', 'layout_mode', 'layout_params')
: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'
Expand Down Expand Up @@ -70,7 +70,10 @@ def __init__(self,

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']
@property
def wake_model(self) -> str:
try:
Expand Down
4 changes: 2 additions & 2 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
NREL-PySAM==3.0.0
NREL-PySAM>=3.0.0
Pillow
Pyomo>=6.1.2
floris
future
global_land_mask
Cython
matplotlib
numpy
numpy>=1.21.0
pandas
pint
pvmismatch
Expand Down
4 changes: 2 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
NREL-PySAM==3.0.0
NREL-PySAM>=3.0.0
Pillow
Pyomo>=6.1.2
floris
future
global_land_mask
Cython
matplotlib
numpy
numpy>=1.21.0
pandas
multiprocessing-on-dill
pint
Expand Down
2 changes: 0 additions & 2 deletions resource_files/site_details.csv

This file was deleted.

Loading