Merge pull request 'floris_design' (#7) from floris_design into main

Reviewed-on: #7
This commit is contained in:
maxim 2024-11-24 14:13:10 +04:00
commit 0aafeda77d
4 changed files with 108 additions and 30 deletions

View File

@ -1,7 +1,9 @@
import math
import os.path
import sys
import uuid
from pathlib import Path
from typing import Set
from floris import FlorisModel
from floris.flow_visualization import visualize_cut_plane
@ -10,7 +12,6 @@ import floris.layout_visualization as layoutviz
import matplotlib.pyplot as plt
_wind_direction_to_val: dict[str, float] = {
"N": 0.0,
"E": 90.0,
@ -53,22 +54,90 @@ class FlorisULSTU(FlorisModel):
super().set(**kwargs)
def visualisation(self):
def visualization(
self,
interest_plots: Set[str]
):
dct_functions = {
"horizontal_plane": self._horizontal_plane_visualization,
"vertical_plane": self._vertical_plane_visualization,
}
res = {}
self.reset_operation()
for param in interest_plots:
if param not in dct_functions:
res[param] = "Not found"
continue
res[param] = dct_functions[param]()
horizontal_plane = self.calculate_horizontal_plane(height=90.0)
visualize_cut_plane(
horizontal_plane,
)
return res
def _horizontal_plane_visualization(self):
return self._plane_visualization(self.calculate_horizontal_plane, {"height": 90.0})
def _vertical_plane_visualization(self):
return self._plane_visualization(self.calculate_y_plane,
{"crossstream_dist": 0.0,
"x_resolution": 200,
"z_resolution": 100})
def _plane_visualization(self, plane_func, func_params: dict[str, float] = {}):
wind_dirs = self.core.flow_field.wind_directions
wind_speeds = self.core.flow_field.wind_speeds
experiment_counts = len(wind_dirs)
near_square = math.ceil(math.sqrt(experiment_counts))
fig, ax_arr = plt.subplots(near_square, near_square, figsize=(15, 8))
ax_arr = ax_arr.flatten()
for experiment_count in range(experiment_counts):
self.reset_operation()
self.set(wind_speeds=[wind_speeds[experiment_count]], wind_directions=[wind_dirs[experiment_count]],
turbulence_intensities=[0.05])
ax = ax_arr[experiment_count]
plane = plane_func(**func_params)
visualize_cut_plane(
plane,
ax=ax,
title=f"Wind flow day {experiment_count + 1}",
)
# plot_turbine_labels(self, axarr[0, 0])
filename = str(uuid.uuid4()) + ".png"
plt.savefig(Path(__file__).parent.parent.parent / f"public/floris/{filename}")
plt.close()
self.set(wind_speeds=wind_speeds, wind_directions=wind_dirs, turbulence_intensities=[0.05] * len(wind_dirs))
return filename
def _cross_visualization(self, plane_func, func_params: dict[str, float] = {}):
wind_dirs = self.core.flow_field.wind_directions
wind_speeds = self.core.flow_field.wind_speeds
experiment_counts = len(wind_dirs)
near_square = math.ceil(math.sqrt(experiment_counts))
fig, ax_arr = plt.subplots(near_square, near_square, figsize=(15, 8))
ax_arr = ax_arr.flatten()
for experiment_count in range(experiment_counts):
self.reset_operation()
self.set(wind_speeds=[wind_speeds[experiment_count]], wind_directions=[wind_dirs[experiment_count]],
turbulence_intensities=[0.05])
ax = ax_arr[experiment_count]
plane = plane_func(**func_params)
visualize_cut_plane(
plane,
ax=ax,
title=f"Wind flow day {experiment_count + 1}",
)
filename = str(uuid.uuid4()) + ".png"
plt.savefig(Path(__file__).parent.parent.parent / f"public/floris/{filename}")
plt.close()
self.set(wind_speeds=wind_speeds, wind_directions=wind_dirs, turbulence_intensities=[0.05] * len(wind_dirs))
return filename

View File

@ -17,7 +17,7 @@ class OpenMeteoClient:
params = {
"latitude": latitude,
"longitude": longitude,
"hourly": ["wind_speed_10m", "wind_direction_10m"],
"daily": ["wind_speed_10m_max", "wind_direction_10m_dominant"],
"timezone": self.timezone,
"start_date": start_date,
"end_date": end_date
@ -27,13 +27,13 @@ class OpenMeteoClient:
def process_response(self, response):
# Process hourly data
hourly = response.Hourly()
hourly_wind_speed_10m = hourly.Variables(0).ValuesAsNumpy()
hourly_wind_direction_10m = hourly.Variables(1).ValuesAsNumpy()
daily = response.Daily()
daily_wind_speed_10m = daily.Variables(0).ValuesAsNumpy()
daily_wind_direction_10m = daily.Variables(1).ValuesAsNumpy()
return hourly_wind_speed_10m.tolist(), hourly_wind_direction_10m.tolist()
return daily_wind_speed_10m.tolist(), daily_wind_direction_10m.tolist()
def get_weather_info(self, latitude, longitude, start_date, end_date):
def get_weather_info(self, start_date, end_date, latitude=54.35119762746125, longitude=48.389356992149345):
responses = self.fetch_weather_data(latitude, longitude, start_date, end_date)
response = responses[0]
self.process_response(response)

View File

@ -14,13 +14,15 @@ class SWeatherInfo(BaseModel):
class SFlorisInputParams(BaseModel):
layout_x: list[float] = Field(Query([]))
layout_y: list[float] = Field(Query([]))
yaw_angle: list[float] = Field(Query([]))
plots: set[str] = Field(Query(["horizontal_plane"]))
date_start: date
date_end: date
class SFlorisOutputData(BaseModel):
file_name: str
data: list[float]
file_name: object
data: object
class WindTurbineTypeBase(BaseModel):
@ -108,4 +110,4 @@ class WindTurbineWithParkDetailsResponse(BaseModel):
comment: Optional[str]
class Config:
orm_mode = True
orm_mode = True

View File

@ -8,12 +8,14 @@ from fastapi.responses import FileResponse
from data.repository import WeatherRepository
from data.schemas import SFlorisInputParams, SFlorisOutputData, SWeatherInfo
import numpy as np
sys.path.append(str(Path(__file__).parent.parent.parent))
from floris_module.src import FlorisULSTU
from floris_module.src.OpenMeteoClient import OpenMeteoClient
FLORIS_IMAGES_PATH = Path(__file__).parent.parent.parent / "public" / "floris"
router = APIRouter(
@ -26,23 +28,20 @@ router = APIRouter(
async def get_windmill_data(
data: Annotated[SFlorisInputParams, Depends()]
):
if len(data.layout_x) != len(data.layout_y):
if len(data.layout_x) != len(data.layout_y) and len(data.layout_x) != len(data.yaw_angle):
raise HTTPException(
status_code=HTTPStatus.BAD_REQUEST,
detail="Length of layout x and y must be the same",
detail="Length of layout x and y and yaw_angle must be the same",
)
fmodel = FlorisULSTU()
client = OpenMeteoClient()
wind_directions = list()
wind_speeds = list()
for i in range(len(data.layout_x)):
i_result = client.get_weather_info(data.layout_x[i], data.layout_y[i], data.date_start, data.date_end)
wind_speeds.extend(i_result[0])
wind_directions.extend(i_result[1])
climate_info = client.get_weather_info(data.date_start, data.date_end)
wind_speeds = climate_info[0]
wind_directions = climate_info[1]
fmodel.set(
layout_x=data.layout_x,
@ -52,14 +51,22 @@ async def get_windmill_data(
turbulence_intensities=[0.1] * len(wind_directions)
)
yaw_angles = np.zeros((len(wind_directions), len(data.layout_x)))
for i in range(len(data.layout_x)):
yaw_angles[:, i] = data.yaw_angle[i]
fmodel.set(
yaw_angles=yaw_angles,
)
fmodel.run()
data = fmodel.get_turbine_powers()[0].tolist()
file_name = fmodel.visualisation()
res = fmodel.get_turbine_powers().tolist()
file_names = fmodel.visualization(data.plots)
return SFlorisOutputData(
file_name=file_name,
data=data
file_name=file_names,
data=res
)