예제 #1
0
def turbine_grid_fixture(sample_inputs_fixture) -> TurbineGrid:
    turbine_coordinates = [
        Vec3(c) for c in list(zip(X_COORDS, Y_COORDS, Z_COORDS))
    ]

    # TODO: The TurbineGrid requires that the rotor diameters be 1d but the Farm constructs them as 3d
    #   Can we make this consistent?

    rotor_diameters = ROTOR_DIAMETER * np.ones((N_TURBINES))
    return TurbineGrid(turbine_coordinates=turbine_coordinates,
                       reference_turbine_diameter=rotor_diameters,
                       wind_directions=np.array(WIND_DIRECTIONS),
                       wind_speeds=np.array(WIND_SPEEDS),
                       grid_resolution=TURBINE_GRID_RESOLUTION)
예제 #2
0
def full_flow_cc_solver(farm: Farm, flow_field: FlowField, flow_field_grid: FlowFieldGrid, model_manager: WakeModelManager) -> None:
    # Get the flow quantities and turbine performance
    turbine_grid_farm = copy.deepcopy(farm)
    turbine_grid_flow_field = copy.deepcopy(flow_field)

    turbine_grid_farm.construct_turbine_map()
    turbine_grid_farm.construct_turbine_fCts()
    turbine_grid_farm.construct_turbine_fCps()
    turbine_grid_farm.construct_turbine_power_interps()
    turbine_grid_farm.construct_hub_heights()
    turbine_grid_farm.construct_rotor_diameters()
    turbine_grid_farm.construct_turbine_TSRs()
    turbine_grid_farm.construc_turbine_pPs()
    turbine_grid_farm.construct_coordinates()

    turbine_grid = TurbineGrid(
        turbine_coordinates=turbine_grid_farm.coordinates,
        reference_turbine_diameter=turbine_grid_farm.rotor_diameters_sorted,
        wind_directions=turbine_grid_flow_field.wind_directions,
        wind_speeds=turbine_grid_flow_field.wind_speeds,
        grid_resolution=3,
    )
    turbine_grid_farm.expand_farm_properties(
        turbine_grid_flow_field.n_wind_directions, turbine_grid_flow_field.n_wind_speeds, turbine_grid.sorted_coord_indices
    )
    turbine_grid_flow_field.initialize_velocity_field(turbine_grid)
    turbine_grid_farm.initialize(turbine_grid.sorted_indices)
    cc_solver(turbine_grid_farm, turbine_grid_flow_field, turbine_grid, model_manager)

    ### Referring to the quantities from above, calculate the wake in the full grid

    # Use full flow_field here to use the full grid in the wake models
    deflection_model_args = model_manager.deflection_model.prepare_function(flow_field_grid, flow_field)
    deficit_model_args = model_manager.velocity_model.prepare_function(flow_field_grid, flow_field)

    v_wake = np.zeros_like(flow_field.v_initial_sorted)
    w_wake = np.zeros_like(flow_field.w_initial_sorted)
    turb_u_wake = np.zeros_like(flow_field.u_initial_sorted)

    shape = (farm.n_turbines,) + np.shape(flow_field.u_initial_sorted)
    Ctmp = np.zeros((shape))

    # Calculate the velocity deficit sequentially from upstream to downstream turbines
    for i in range(flow_field_grid.n_turbines):

        # Get the current turbine quantities
        x_i = np.mean(turbine_grid.x_sorted[:, :, i:i+1], axis=(3, 4))
        x_i = x_i[:, :, :, None, None]
        y_i = np.mean(turbine_grid.y_sorted[:, :, i:i+1], axis=(3, 4))        
        y_i = y_i[:, :, :, None, None]
        z_i = np.mean(turbine_grid.z_sorted[:, :, i:i+1], axis=(3, 4))
        z_i = z_i[:, :, :, None, None]

        u_i = turbine_grid_flow_field.u_sorted[:, :, i:i+1]
        v_i = turbine_grid_flow_field.v_sorted[:, :, i:i+1]

        turb_avg_vels = average_velocity(turbine_grid_flow_field.u_sorted)
        turb_Cts = Ct(
            velocities=turb_avg_vels,
            yaw_angle=turbine_grid_farm.yaw_angles_sorted,
            fCt=turbine_grid_farm.turbine_fCts,
            turbine_type_map=turbine_grid_farm.turbine_type_map_sorted,
        )
        turb_Cts = turb_Cts[:, :, :, None, None]

        axial_induction_i = axial_induction(
            velocities=turbine_grid_flow_field.u_sorted,
            yaw_angle=turbine_grid_farm.yaw_angles_sorted,
            fCt=turbine_grid_farm.turbine_fCts,
            turbine_type_map=turbine_grid_farm.turbine_type_map_sorted,
            ix_filter=[i],
        )
        axial_induction_i = axial_induction_i[:, :, :, None, None]

        turbulence_intensity_i = turbine_grid_flow_field.turbulence_intensity_field[:, :, i:i+1]
        yaw_angle_i = turbine_grid_farm.yaw_angles_sorted[:, :, i:i+1, None, None]
        hub_height_i = turbine_grid_farm.hub_heights_sorted[: ,:, i:i+1, None, None]
        rotor_diameter_i = turbine_grid_farm.rotor_diameters_sorted[: ,:, i:i+1, None, None]
        TSR_i = turbine_grid_farm.TSRs_sorted[: ,:, i:i+1, None, None]

        effective_yaw_i = np.zeros_like(yaw_angle_i)
        effective_yaw_i += yaw_angle_i

        if model_manager.enable_secondary_steering:
            added_yaw = wake_added_yaw(
                u_i,
                v_i,
                turbine_grid_flow_field.u_initial_sorted,
                turbine_grid.y_sorted[:, :, i:i+1] - y_i,
                turbine_grid.z_sorted[:, :, i:i+1],
                rotor_diameter_i,
                hub_height_i,
                turb_Cts[:, :, i:i+1],
                TSR_i,
                axial_induction_i,
                scale=2.0
            )
            effective_yaw_i += added_yaw

        # Model calculations
        # NOTE: exponential
        deflection_field = model_manager.deflection_model.function(
            x_i,
            y_i,
            effective_yaw_i,
            turbulence_intensity_i,
            turb_Cts[:, :, i:i+1],
            rotor_diameter_i,
            **deflection_model_args
        )

        if model_manager.enable_transverse_velocities:
            v_wake, w_wake = calculate_transverse_velocity(
                u_i,
                flow_field.u_initial_sorted,
                flow_field_grid.x_sorted - x_i,
                flow_field_grid.y_sorted - y_i,
                flow_field_grid.z_sorted,
                rotor_diameter_i,
                hub_height_i,
                yaw_angle_i,
                turb_Cts[:, :, i:i+1],
                TSR_i,
                axial_induction_i,
                scale=2.0
            )

        # NOTE: exponential
        turb_u_wake, Ctmp = model_manager.velocity_model.function(
            i,
            x_i,
            y_i,
            z_i,
            u_i,
            deflection_field,
            yaw_angle_i,
            turbine_grid_flow_field.turbulence_intensity_field,
            turb_Cts,
            turbine_grid_farm.rotor_diameters_sorted[:, :, :, None, None],
            turb_u_wake,
            Ctmp,
            **deficit_model_args
        )

        flow_field.v_sorted += v_wake
        flow_field.w_sorted += w_wake
    flow_field.u_sorted = flow_field.u_initial_sorted - turb_u_wake
예제 #3
0
    def __attrs_post_init__(self) -> None:

        # Initialize farm quanitities that depend on other objects
        self.farm.construct_turbine_map()
        self.farm.construct_turbine_fCts()
        self.farm.construct_turbine_fCps()
        self.farm.construct_turbine_power_interps()
        self.farm.construct_hub_heights()
        self.farm.construct_rotor_diameters()
        self.farm.construct_turbine_TSRs()
        self.farm.construc_turbine_pPs()
        self.farm.construct_coordinates()
        self.farm.set_yaw_angles(self.flow_field.n_wind_directions,
                                 self.flow_field.n_wind_speeds)

        if self.solver["type"] == "turbine_grid":
            self.grid = TurbineGrid(
                turbine_coordinates=self.farm.coordinates,
                reference_turbine_diameter=self.farm.rotor_diameters,
                wind_directions=self.flow_field.wind_directions,
                wind_speeds=self.flow_field.wind_speeds,
                grid_resolution=self.solver["turbine_grid_points"],
            )
        elif self.solver["type"] == "flow_field_grid":
            self.grid = FlowFieldGrid(
                turbine_coordinates=self.farm.coordinates,
                reference_turbine_diameter=self.farm.rotor_diameters,
                wind_directions=self.flow_field.wind_directions,
                wind_speeds=self.flow_field.wind_speeds,
                grid_resolution=self.solver["flow_field_grid_points"],
            )
        elif self.solver["type"] == "flow_field_planar_grid":
            self.grid = FlowFieldPlanarGrid(
                turbine_coordinates=self.farm.coordinates,
                reference_turbine_diameter=self.farm.rotor_diameters,
                wind_directions=self.flow_field.wind_directions,
                wind_speeds=self.flow_field.wind_speeds,
                normal_vector=self.solver["normal_vector"],
                planar_coordinate=self.solver["planar_coordinate"],
                grid_resolution=self.solver["flow_field_grid_points"],
                x1_bounds=self.solver["flow_field_bounds"][0],
                x2_bounds=self.solver["flow_field_bounds"][1],
            )
        else:
            raise ValueError(
                f"Supported solver types are [turbine_grid, flow_field_grid], but type given was {self.solver['type']}"
            )

        if type(self.grid) == TurbineGrid:
            self.farm.expand_farm_properties(self.flow_field.n_wind_directions,
                                             self.flow_field.n_wind_speeds,
                                             self.grid.sorted_coord_indices)

        # Configure logging
        logging_manager.configure_console_log(
            self.logging["console"]["enable"],
            self.logging["console"]["level"],
        )
        logging_manager.configure_file_log(
            self.logging["file"]["enable"],
            self.logging["file"]["level"],
        )