def _lookup_costs(self, wind_mw, solar_mw, interconnection_mw): if wind_mw + solar_mw == 0: return 0, 0, 0 search_inputs = np.array([interconnection_mw, wind_mw, solar_mw]) distance_norm = np.linalg.norm(self.contents - search_inputs, axis=1) min_index = np.argmin(distance_norm) min_distance = distance_norm[min_index] vals = [] for i in range(len(self.desired_output_parameters)): vals.append(self.interpolating_fxns[i](search_inputs)[0]) if np.isnan(vals).any(): if min_distance / np.linalg.norm(search_inputs) < .05: wind_bos_cost = self.data.iloc[min_index:min_index+1]["Wind BOS Cost"].values solar_bos_cost = self.data.iloc[min_index:min_index+1]["Solar BOS Cost"].values else: raise ValueError("Inputs to BOSLookup outside of range and cannot be extrapolated") else: wind_bos_cost = vals[self.desired_output_parameters.index("Wind BOS Cost")] solar_bos_cost = vals[self.desired_output_parameters.index("Solar BOS Cost")] total_bos_cost = wind_bos_cost + solar_bos_cost logger.info("Total BOS Cost: {} Wind BOS Cost: {} Solar BOS Cost {}". format(total_bos_cost, wind_bos_cost, solar_bos_cost)) return wind_bos_cost, solar_bos_cost, total_bos_cost, min_distance
def _calculate_greenfield(self, wind_mw: float, solar_mw: float, interconnection_mw: float = 0): logger.info("Implemented") specify_construction_duration = False return HybridBOSSE._calculate(wind_mw, solar_mw, interconnection_mw, specify_construction_duration)
def calculate_total_costs(self, wind_mw, solar_mw): """ Calculates total installed cost of plant (BOS Cost + Installed Cost). Modifies the capex or opex costs as specified in cost_reductions if modify_costs is True :return: Total installed cost of plant (BOS Cost + Installed Cost) """ logger.info( "Determining total costs for Wind size: {}MW and Solar size: {}MW and Interconnection size: {}MW" .format(wind_mw, solar_mw, self.interconnection_size)) logger.info( "Using {}$/MW for installed Wind cost and {}$/MW for installed Solar cost" .format(self.wind_installed_cost_mw, self.solar_installed_cost_mw)) logger.info("Using '{}' to determine BOS costs".format( self.model.name)) wind_installed_cost, solar_installed_cost, total_installed_cost = self.calculate_installed_costs( wind_mw, solar_mw) wind_bos_cost, solar_bos_cost, total_bos_cost, _ = self.model.calculate_bos_costs( wind_mw, solar_mw, self.interconnection_size, self.scenario) total_wind_cost = wind_installed_cost + wind_bos_cost total_solar_cost = solar_installed_cost + solar_bos_cost total_project_cost = total_installed_cost + total_bos_cost if self.modify_costs: logger.info('Modifying costs using selected multipliers') logger.info("Total Project Cost Before Modifiers: {}".format( total_project_cost)) if wind_mw > 0 and solar_mw > 0: total_project_cost = ((1 - self.cost_reductions['solar_capex_reduction_hybrid']) * solar_installed_cost) + \ ((1 - self.cost_reductions[ 'solar_bos_reduction_hybrid']) * solar_bos_cost) + \ ((1 - self.cost_reductions['wind_capex_reduction_hybrid']) * wind_installed_cost) + \ ((1 - self.cost_reductions[ 'wind_bos_reduction_hybrid']) * wind_bos_cost) elif solar_mw > 0: total_project_cost = ((1 - self.cost_reductions['solar_capex_reduction']) * solar_installed_cost) + \ ((1 - self.cost_reductions['solar_bos_reduction']) * solar_bos_cost) elif wind_mw > 0: total_project_cost = ((1 - self.cost_reductions['wind_capex_reduction']) * wind_installed_cost) + \ ((1 - self.cost_reductions['wind_bos_reduction']) * wind_bos_cost) logger.info("Total Project Cost After Modifiers: {}".format( total_project_cost)) # else: # logger.info('Not modifying costs') # Not modifying wind or solar costs logger.info( "Total Project Cost (Installed Cost + BOS Cost): {}".format( total_project_cost)) return total_solar_cost, total_wind_cost, total_project_cost
def _calculate(wind_size, solar_size, interconnection_rating, specify_construction_duration): warnings.filterwarnings('ignore') # ignore pandas FutureWarning hybrids_input_dict = dict() # shared infra inputs hybrids_input_dict['shared_interconnection'] = True hybrids_input_dict[ 'distance_to_interconnect_mi'] = 1 # Input not used for projects <= 15 MW hybrids_input_dict['new_switchyard'] = True grid_size_multiplier = 1 grid_size = wind_size * grid_size_multiplier if grid_size > 15: hybrids_input_dict['distance_to_interconnect_mi'] = ( 0.0263 * grid_size) - 0.2632 else: hybrids_input_dict['distance_to_interconnect_mi'] = 0 if grid_size < 20: hybrids_input_dict['interconnect_voltage_kV'] = 15 elif 20 < grid_size < 40: hybrids_input_dict['interconnect_voltage_kV'] = 34.5 elif 40 <= grid_size < 75: hybrids_input_dict['interconnect_voltage_kV'] = 69 # should be 69 elif grid_size >= 75: hybrids_input_dict[ 'interconnect_voltage_kV'] = 138 # should be 138 hybrids_input_dict[ 'grid_interconnection_rating_MW'] = wind_size + solar_size hybrids_input_dict['shared_substation'] = True hybrids_input_dict[ 'hybrid_substation_rating_MW'] = wind_size + solar_size # Wind farm required inputs hybrids_input_dict['turbine_rating_MW'] = 1.5 num_turbines = math.ceil(wind_size / hybrids_input_dict['turbine_rating_MW']) hybrids_input_dict['num_turbines'] = num_turbines hybrids_input_dict[ 'wind_dist_interconnect_mi'] = 0 # Only used for calculating grid cost of wind only. Input not used for projects <= 15 MW hybrids_input_dict['wind_construction_time_months'] = 5 hybrids_input_dict['project_id'] = 'hybrids' # Solar farm required inputs hybrids_input_dict['solar_system_size_MW_DC'] = solar_size hybrids_input_dict[ 'solar_construction_time_months'] = 5 # Optional. Overrides the internal scaling MW vs. construction time relationship hybrids_input_dict['solar_dist_interconnect_mi'] = 0 # pre-processed input data: hybrids_input_dict['wind_plant_size_MW'] = hybrids_input_dict['num_turbines'] * \ hybrids_input_dict['turbine_rating_MW'] hybrids_input_dict['hybrid_plant_size_MW'] = hybrids_input_dict['wind_plant_size_MW'] + \ hybrids_input_dict['solar_system_size_MW_DC'] hybrids_input_dict['hybrid_construction_months'] = \ hybrids_input_dict['wind_construction_time_months'] + \ hybrids_input_dict['solar_construction_time_months'] hybrid_results, wind_only, solar_only = run_hybridbosse( hybrids_input_dict) logger.info('Hybrid Dictionary Results: {}'.format(hybrid_results)) logger.info('Wind Only Dictionary Results:'.format(wind_only)) logger.info('Solar Only Dictionary Results:'.format(solar_only)) wind_hybrid_bos_cost = hybrid_results['Wind_BOS_results'][ 'total_bos_cost'] solar_hybrid_bos_cost = hybrid_results['Solar_BOS_results'][ 'total_bos_cost'] hybrid_total_bos_cost = wind_hybrid_bos_cost + solar_hybrid_bos_cost #hybrid_results['hybrid']['hybrid_BOS_usd'] return wind_hybrid_bos_cost, solar_hybrid_bos_cost, hybrid_total_bos_cost
def calculate_total_costs(self, wind_mw, pv_mw, storage_mw=0., storage_mwh=0.): """ Calculates total installed cost of plant (BOS Cost + Installed Cost). Modifies the capex or opex costs as specified in cost_reductions if modify_costs is True :return: Total installed cost of plant (BOS Cost + Installed Cost) """ wind_installed_cost, solar_installed_cost, storage_installed_cost, total_installed_cost = \ self.calculate_installed_costs(wind_mw, pv_mw, storage_mw, storage_mwh) if self.bos_cost_source.lower() == 'costpermw': wind_bos_cost, solar_bos_cost, storage_bos_cost, total_bos_cost, _ = \ self.model.calculate_bos_costs(wind_mw, pv_mw, storage_mw, storage_mwh, self.wind_bos_cost_mw, self.pv_bos_cost_mw, self.storage_bos_cost_mw, self.storage_bos_cost_mwh, self.interconnection_size, self.scenario) else: wind_bos_cost, solar_bos_cost, total_bos_cost, min_distance = \ self.model.calculate_bos_costs(wind_mw, pv_mw, self.interconnection_size) storage_bos_cost = 0. total_wind_cost = wind_installed_cost + wind_bos_cost total_solar_cost = solar_installed_cost + solar_bos_cost total_storage_cost = storage_installed_cost + storage_bos_cost total_project_cost = total_installed_cost + total_bos_cost if self.modify_costs: logger.info('Modifying costs using selected multipliers') logger.info("Total Project Cost Before Modifiers: {}".format( total_project_cost)) if wind_mw > 0 and pv_mw > 0: total_project_cost = ((1 - self.cost_reductions['solar_capex_reduction_hybrid']) * solar_installed_cost) + \ ((1 - self.cost_reductions[ 'solar_bos_reduction_hybrid']) * solar_bos_cost) + \ ((1 - self.cost_reductions['wind_capex_reduction_hybrid']) * wind_installed_cost) + \ ((1 - self.cost_reductions[ 'wind_bos_reduction_hybrid']) * wind_bos_cost) elif pv_mw > 0: total_project_cost = ((1 - self.cost_reductions['solar_capex_reduction']) * solar_installed_cost) + \ ((1 - self.cost_reductions['solar_bos_reduction']) * solar_bos_cost) elif wind_mw > 0: total_project_cost = ((1 - self.cost_reductions['wind_capex_reduction']) * wind_installed_cost) + \ ((1 - self.cost_reductions['wind_bos_reduction']) * wind_bos_cost) logger.info("Total Project Cost After Modifiers: {}".format( total_project_cost)) # else: # logger.info('Not modifying costs') # Not modifying wind or solar costs logger.info( "Total Project Cost (Installed Cost + BOS Cost): {}".format( total_project_cost)) return total_solar_cost, total_wind_cost, total_storage_cost, total_project_cost