Source code for ard.layout.viewshed

import numpy as np

from shapely.geometry import Point
from shapely.ops import unary_union

import openmdao.api as om

_R_earth = 6371008.8  # Earth radius, m


[docs] def calculate_viewshed_section_angle( D_rotor: float, # rotor diameter, m h_hub: float, # hub height, m R_earth: float = _R_earth, # Earth radius, m h_terrain: float = 0.0, # mean height of prevailing terrain wrt turbine base, m ) -> float: # returns arc angle (rad) of viewshed H = D_rotor / 2 + h_hub - h_terrain return np.arccos(R_earth / (R_earth + H))
[docs] def calculate_viewshed_arc_length( D_rotor: float, # rotor diameter, m h_hub: float, # hub height, m R_earth: float = _R_earth, # Earth radius, m h_terrain: float = 0.0, # mean height of prevailing terrain wrt turbine base, m ) -> float: # returns arc length of viewshed angle_arc = calculate_viewshed_section_angle( D_rotor, h_hub, R_earth=R_earth, h_terrain=h_terrain, ) return R_earth * angle_arc
[docs] def calculate_viewshed_arc_length_smallangle( D_rotor: float, # rotor diameter, m h_hub: float, # hub height, m R_earth: float = _R_earth, # Earth radius, m h_terrain: float = 0.0, # mean height of prevailing terrain wrt turbine base, m ) -> float: # returns arc length of viewshed angle_arc = calculate_viewshed_section_angle( D_rotor, h_hub, R_earth=R_earth, h_terrain=h_terrain, ) return R_earth * np.sin(angle_arc)
[docs] class ViewshedAreaComp(om.ExplicitComponent):
[docs] def initialize(self): self.options.declare("modeling_options")
[docs] def setup(self): self.modeling_options = self.options["modeling_options"] self.windIO = self.modeling_options["windIO_plant"] self.D_rotor = self.windIO["wind_farm"]["turbine"]["rotor_diameter"] self.h_hub = self.windIO["wind_farm"]["turbine"]["hub_height"] self.N_turbines = self.modeling_options["layout"]["N_turbines"] self.add_input("x_turbines", np.zeros((self.N_turbines,)), units="m") self.add_input("y_turbines", np.zeros((self.N_turbines,)), units="m") # self.add_output('viewshed_arc_length', val=0.0, units='m', desc='Viewshed arc length') self.add_output("area_viewshed", val=0.0, units="km**2", desc="Viewshed area")
[docs] def setup_partials(self): # declare FD because no derivative is available self.declare_partials("area_viewshed", "*", method="fd")
[docs] def compute(self, inputs, outputs): # get the single-turbine viewshed arc length D_rotor = self.D_rotor h_hub = self.h_hub h_terrain = 0.0 # project onto 2D surface plane x_turbines = inputs["x_turbines"] y_turbines = inputs["y_turbines"] D_rotor_turbines = D_rotor * np.ones_like(x_turbines) h_hub_turbines = h_hub * np.ones_like(x_turbines) R_viewshed_turbines = calculate_viewshed_arc_length( D_rotor_turbines, h_hub_turbines, h_terrain=h_terrain, ) # create a list of shapely circles viewshed_circles = [ Point(x, y).buffer(r) for x, y, r in zip( x_turbines.flatten(), y_turbines.flatten(), R_viewshed_turbines.flatten(), ) ] # compute the union of all circles viewshed_union = unary_union(viewshed_circles) # calculate the area of the union in square kilometers viewshed_union_area_km2 = viewshed_union.area / 1e6 # pack and send output outputs["area_viewshed"] = viewshed_union_area_km2