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

Kempe edge seals #134

Open
wants to merge 12 commits into
base: development
Choose a base branch
from
8 changes: 4 additions & 4 deletions pvdeg/data/H2Opermeation.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@
"source": "unpublished measurements",
"Fickian": true,
"Ead": 61.4781422330562,
"Do": 25790.6020262449,
"Do": 257.906020262449,
"Eas": 5.88752263485353,
"So": 0.00982242435416737,
"Eap": 67.3656648679097,
"Po": 5559396276.60964
"So": 0.0982242435416737,
"Eap": 66.9611315410624,
"Po": 189338932521.637
},
"W003": {
"name": "Coveme",
Expand Down
53 changes: 29 additions & 24 deletions pvdeg/geospatial.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ def start_dask(hpc=None):

client = Client(cluster)
print("Dashboard:", client.dashboard_link)
client.wait_for_workers(n_workers=1)
# client.wait_for_workers(n_workers=1)

return client

Expand Down Expand Up @@ -999,7 +999,10 @@ def elevation_stochastic_downselect(


def interpolate_analysis(
result: xr.Dataset, data_var: str, method="nearest", resolution=100j,
result: xr.Dataset,
data_var: str,
method="nearest",
resolution=100j,
) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
"""
Interpolate sparse spatial result data against DataArray coordinates.
Expand Down Expand Up @@ -1037,12 +1040,12 @@ def interpolate_analysis(

# api could be updated to match that of plot_USA
def plot_sparse_analysis(
result: xr.Dataset,
data_var: str,
method="nearest",
resolution:complex=100j,
figsize:tuple=(10,8),
show_plot:bool=False,
result: xr.Dataset,
data_var: str,
method="nearest",
resolution: complex = 100j,
figsize: tuple = (10, 8),
show_plot: bool = False,
) -> None:
"""
Plot the output of a sparse geospatial analysis using interpolation.
Expand All @@ -1054,7 +1057,7 @@ def plot_sparse_analysis(
data_var: str
name of datavariable to plot from result
method: str
interpolation method.
interpolation method.
Options: `'nearest', 'linear', 'cubic'`
See [`scipy.interpolate.griddata`](https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.griddata.html)
resolution: complex
Expand All @@ -1072,7 +1075,9 @@ def plot_sparse_analysis(
)

fig = plt.figure(figsize=figsize)
ax = fig.add_axes([0, 0, 1, 1], projection=ccrs.LambertConformal(), frameon=False) # these should be the same ccrs
ax = fig.add_axes(
[0, 0, 1, 1], projection=ccrs.LambertConformal(), frameon=False
) # these should be the same ccrs
ax.patch.set_visible(False)

extent = [lon.min(), lon.max(), lat.min(), lat.max()]
Expand All @@ -1082,7 +1087,7 @@ def plot_sparse_analysis(
extent=extent,
origin="lower",
cmap="viridis",
transform=ccrs.PlateCarree(), # why are ccrs different
transform=ccrs.PlateCarree(), # why are ccrs different
)

shapename = "admin_1_states_provinces_lakes"
Expand All @@ -1103,22 +1108,22 @@ def plot_sparse_analysis(
plt.title(f"Interpolated Sparse Analysis, {data_var}")
plt.xlabel("Longitude")
plt.ylabel("Latitude")

if show_plot:
plt.show()

return fig, ax


def plot_sparse_analysis_land(
result: xr.Dataset,
data_var: str,
method="nearest",
resolution:complex=100j,
figsize:tuple=(10,8),
show_plot:bool=False,
result: xr.Dataset,
data_var: str,
method="nearest",
resolution: complex = 100j,
figsize: tuple = (10, 8),
show_plot: bool = False,
proj=ccrs.PlateCarree(),
):

import matplotlib.path as mpath
from cartopy.mpl.patch import geos_to_path

Expand All @@ -1133,7 +1138,7 @@ def plot_sparse_analysis_land(
extent = [lon.min(), lon.max(), lat.min(), lat.max()]
ax.set_extent(extent, crs=proj)

mesh = ax.pcolormesh(lon, lat, grid_values, transform=proj, cmap='viridis')
mesh = ax.pcolormesh(lon, lat, grid_values, transform=proj, cmap="viridis")

land_path = geos_to_path(list(cfeature.LAND.geometries()))
land_path = mpath.Path.make_compound_path(*land_path)
Expand All @@ -1150,15 +1155,15 @@ def plot_sparse_analysis_land(
proj,
facecolor="none",
edgecolor="black",
linestyle=':'
linestyle=":",
)

cbar = plt.colorbar(mesh, ax=ax, orientation="vertical", fraction=0.02, pad=0.04)
cbar.set_label("Value")

utilities._add_cartopy_features(
ax=ax,
features = [
ax=ax,
features=[
cfeature.BORDERS,
cfeature.COASTLINE,
cfeature.LAND,
Expand All @@ -1169,4 +1174,4 @@ def plot_sparse_analysis_land(
if show_plot:
plt.show()

return fig, ax
return fig, ax
152 changes: 151 additions & 1 deletion pvdeg/spectral.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,73 @@ def solar_position(weather_df: pd.DataFrame, meta: dict) -> pd.DataFrame:
],
)
def poa_irradiance(
weather_df: pd.DataFrame,
meta: dict,
module_mount="fixed",
sol_position=None,
**kwargs_irradiance,
) -> pd.DataFrame:
"""
Calculate plane-of-array (POA) irradiance using pvlib based on weather data from the
National Solar Radiation Database (NSRDB) for a given location (gid).

Parameters
----------
weather_df : pd.DataFrame
The file path to the NSRDB file.
meta : dict
The geographical location ID in the NSRDB file.
module_mount: string
Module mounting configuration. Can either be `fixed` for fixed tilt systems or
`1_axis` for single-axis tracker systems.
sol_position : pd.DataFrame, optional
pvlib.solarposition.get_solarposition Dataframe. If none is given, it will be calculated.
kwargs_irradiance : dict
Contains kwarg arguments for the poa model based on mounting configuration. See
`poa_irradiance_fixed` or `poa_irradiance_tracker` for details.

Returns
-------
poa : pandas.DataFrame
Contains keys/columns 'poa_global', 'poa_direct', 'poa_diffuse',
'poa_sky_diffuse', 'poa_ground_diffuse'. [W/m2]
"""

if sol_position is None:
sol_position = solar_position(weather_df, meta)

if module_mount == "fixed":
poa = poa_irradiance_fixed(weather_df, meta, sol_position, **kwargs_irradiance)
elif module_mount == "1_axis":
poa = poa_irradiance_tracker(
weather_df, meta, sol_position, **kwargs_irradiance
)
else:
raise NotImplementedError(
f"The input module_mount '{module_mount}' is not implemented"
)

return poa


@geospatial_quick_shape(
1,
[
"poa_global",
"poa_direct",
"poa_diffuse",
"poa_sky_diffuse",
"poa_ground_diffuse",
],
)
def poa_irradiance_fixed(
weather_df: pd.DataFrame,
meta: dict,
sol_position=None,
tilt=None,
azimuth=None,
sky_model="isotropic",
**kwargs_irradiance,
) -> pd.DataFrame:
"""
Calculate plane-of-array (POA) irradiance using pvlib based on weather data from the
Expand Down Expand Up @@ -104,7 +165,7 @@ def poa_irradiance(
try:
tilt = float(meta["tilt"])
except:
tilt = float(meta["latitude"])
tilt = float(abs(meta["latitude"]))
print(
f"The array tilt angle was not provided, therefore the latitude tilt of {tilt:.1f} was used."
)
Expand Down Expand Up @@ -135,3 +196,92 @@ def poa_irradiance(
)

return poa


@geospatial_quick_shape(
1,
[
"poa_global",
"poa_direct",
"poa_diffuse",
"poa_sky_diffuse",
"poa_ground_diffuse",
],
)
def poa_irradiance_tracker(
weather_df: pd.DataFrame,
meta: dict,
sol_position=None,
axis_tilt=0,
axis_azimuth=None,
max_angle=90,
backtrack=True,
gcr=0.2857142857142857,
cross_axis_tilt=0,
sky_model="isotropic",
**kwargs_irradiance,
) -> pd.DataFrame:
"""
Calculate plane-of-array (POA) irradiance using pvlib based on weather data from the
National Solar Radiation Database (NSRDB) for a given location (gid).

Parameters
----------
weather_df : pd.DataFrame
The file path to the NSRDB file.
meta : dict
The geographical location ID in the NSRDB file.
sol_position : pd.DataFrame, optional
pvlib.solarposition.get_solarposition Dataframe. If none is given, it will be calculated.
tilt : float, optional
The tilt angle of the PV panels in degrees, if None, the latitude of the
location is used.
azimuth : float, optional
The azimuth angle of the PV panels in degrees. Equatorial facing by default.
sky_model : str, optional
The pvlib sky model to use, 'isotropic' by default.
Options: 'isotropic', 'klucher', 'haydavies', 'reindl', 'king', 'perez'.

Returns
-------
tracker_poa : pandas.DataFrame
Contains keys/columns 'poa_global', 'poa_direct', 'poa_diffuse',
'poa_sky_diffuse', 'poa_ground_diffuse'. [W/m2]
"""

if axis_azimuth is None: # Sets the default orientation to north-south.
try:
axis_azimuth = float(meta["axis_azimuth"])
except:
if float(meta["latitude"]) < 0:
axis_azimuth = 0
else:
axis_azimuth = 180
print(f"The array axis_azimuth was not provided, therefore an azimuth of {axis_azimuth:.1f} was used.")

if sol_position is None:
sol_position = solar_position(weather_df, meta)

tracker_data = pvlib.tracking.singleaxis(
sol_position["apparent_zenith"],
sol_position["azimuth"],
axis_tilt=axis_tilt,
axis_azimuth=axis_azimuth,
max_angle=max_angle,
backtrack=backtrack,
gcr=gcr,
cross_axis_tilt=cross_axis_tilt,
)

tracker_poa = pvlib.irradiance.get_total_irradiance(
surface_tilt=tracker_data["surface_tilt"],
surface_azimuth=tracker_data["surface_azimuth"],
dni=weather_df["dni"],
ghi=weather_df["ghi"],
dhi=weather_df["dhi"],
solar_zenith=sol_position["apparent_zenith"],
solar_azimuth=sol_position["azimuth"],
model=sky_model,
)

return tracker_poa
Loading
Loading