diff --git a/HISTORY.rst b/HISTORY.rst index 9c17fb57a..4fd856681 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -62,7 +62,6 @@ Unreleased Changes versions of InVEST would skip these parameters' type-specific validation. Now, these parameters will be validated with their type-specific validation checks. - * Annual Water Yield * Added the results_suffix to a few intermediate files where it was missing. https://github.com/natcap/invest/issues/1517 @@ -71,6 +70,17 @@ Unreleased Changes raster. ``nan`` pixels will now be propertly ignored before calculating mean depths along fetch rays. https://github.com/natcap/invest/issues/1528 +* SDR + * Fixed an issue encountered in the sediment deposition function where + rasters with more than 2^32 pixels would raise a cryptic error relating + to negative dimensions. https://github.com/natcap/invest/issues/1431 + * Optimized the creation of the summary vector by minimizing the number of + times the target vector needs to be rasterized. +* Wind Energy + * Fixed a bug where some number inputs were not being properly cast to + ``float`` or ``int`` types. If the inputs happened to be passed as + a ``str`` this caused unintended side effects such as a concatenation + error. (https://github.com/natcap/invest/issues/1498) * Urban Nature Access * Fixed a ``NameError`` that occurred when running the model using search radii defined per population group with an exponential search @@ -94,12 +104,6 @@ Unreleased Changes * Fixed an issue where an LULC raster without a nodata value would always raise in exception during reclassification. https://github.com/natcap/invest/issues/1539 -* SDR - * Fixed an issue encountered in the sediment deposition function where - rasters with more than 2^32 pixels would raise a cryptic error relating - to negative dimensions. https://github.com/natcap/invest/issues/1431 - * Optimized the creation of the summary vector by minimizing the number of - times the target vector needs to be rasterized. 3.14.1 (2023-12-18) ------------------- diff --git a/src/natcap/invest/wind_energy.py b/src/natcap/invest/wind_energy.py index e3947dbf0..252e4811d 100644 --- a/src/natcap/invest/wind_energy.py +++ b/src/natcap/invest/wind_energy.py @@ -1289,10 +1289,15 @@ def execute(args): levelized_raster_path = os.path.join( out_dir, 'levelized_cost_price_per_kWh%s.tif' % suffix) + # Include foundation_cost, discount_rate, number_of_turbines with + # parameters_dict to pass for NPV calculation + for key in ['foundation_cost', 'discount_rate', 'number_of_turbines']: + parameters_dict[key] = float(args[key]) + task_graph.add_task( func=_calculate_npv_levelized_rasters, args=(harvested_masked_path, final_dist_raster_path, npv_raster_path, - levelized_raster_path, parameters_dict, args, price_list), + levelized_raster_path, parameters_dict, price_list), target_path_list=[npv_raster_path, levelized_raster_path], task_name='calculate_npv_levelized_rasters', dependent_task_list=[final_dist_task]) @@ -1321,7 +1326,7 @@ def execute(args): def _calculate_npv_levelized_rasters( base_harvested_raster_path, base_dist_raster_path, target_npv_raster_path, target_levelized_raster_path, - parameters_dict, args, price_list): + parameters_dict, price_list): """Calculate NPV and levelized rasters from harvested and dist rasters. Args: @@ -1341,9 +1346,6 @@ def _calculate_npv_levelized_rasters( parameters_dict (dict): a dictionary of the turbine and biophysical global parameters. - args (dict): a dictionary that contains information on - ``foundation_cost``, ``discount_rate``, ``number_of_turbines``. - price_list (list): a list of wind energy prices for a period of time. @@ -1375,7 +1377,7 @@ def _calculate_npv_levelized_rasters( # The cost of infield cable in currency units per km infield_cost = parameters_dict['infield_cable_cost'] # The cost of the foundation in currency units - foundation_cost = args['foundation_cost'] + foundation_cost = parameters_dict['foundation_cost'] # The cost of each turbine unit in currency units unit_cost = parameters_dict['turbine_cost'] # The installation cost as a decimal @@ -1385,7 +1387,7 @@ def _calculate_npv_levelized_rasters( # The operations and maintenance costs as a decimal factor of capex_arr op_maint_cost = parameters_dict['operation_maintenance_cost'] # The discount rate as a decimal - discount_rate = args['discount_rate'] + discount_rate = parameters_dict['discount_rate'] # The cost to decommission the farm as a decimal factor of capex_arr decom = parameters_dict['decommission_cost'] # The mega watt value for the turbines in MW @@ -1401,16 +1403,15 @@ def _calculate_npv_levelized_rasters( # The total mega watt capacity of the wind farm where mega watt is the # turbines rated power - total_mega_watt = mega_watt * int(args['number_of_turbines']) + number_of_turbines = int(parameters_dict['number_of_turbines']) + total_mega_watt = mega_watt * number_of_turbines # Total infield cable cost - infield_cable_cost = infield_length * infield_cost * int( - args['number_of_turbines']) + infield_cable_cost = infield_length * infield_cost * number_of_turbines LOGGER.debug('infield_cable_cost : %s', infield_cable_cost) # Total foundation cost - total_foundation_cost = (foundation_cost + unit_cost) * int( - args['number_of_turbines']) + total_foundation_cost = (foundation_cost + unit_cost) * number_of_turbines LOGGER.debug('total_foundation_cost : %s', total_foundation_cost) # Nominal Capital Cost (CAP) minus the cost of cable which needs distances diff --git a/tests/test_wind_energy.py b/tests/test_wind_energy.py index c2b732fb0..209da2f81 100644 --- a/tests/test_wind_energy.py +++ b/tests/test_wind_energy.py @@ -338,13 +338,12 @@ def test_calculate_npv_levelized_rasters(self): 'air_density_coefficient': 1.19E-04, 'loss_parameter': 0.05, 'turbine_cost': 10000, - 'turbine_rated_pwr': 5 - } - args = { + 'turbine_rated_pwr': 5, 'foundation_cost': 1000000, 'discount_rate': 0.01, 'number_of_turbines': 10 } + price_list = [0.10, 0.10, 0.10, 0.10, 0.10] srs = osr.SpatialReference() @@ -381,7 +380,7 @@ def test_calculate_npv_levelized_rasters(self): wind_energy._calculate_npv_levelized_rasters( base_harvest_path, base_distance_path, target_npv_raster_path, target_levelized_raster_path, - val_parameters_dict, args, price_list) + val_parameters_dict, price_list) # Compare the results that were "eye" tested. desired_npv_array = numpy.array( @@ -428,8 +427,8 @@ def generate_base_args(workspace_dir): SAMPLE_DATA, 'global_wind_energy_parameters.csv'), 'turbine_parameters_path': os.path.join( SAMPLE_DATA, '3_6_turbine.csv'), - 'number_of_turbines': 80, - 'min_depth': 3, + 'number_of_turbines': '80', # pass str to test casting + 'min_depth': '3', # pass str to test casting 'max_depth': 180, 'n_workers': -1 } @@ -534,13 +533,13 @@ def test_val_gridpts_windprice(self): args['max_distance'] = 200000 args['valuation_container'] = True args['foundation_cost'] = 2000000 - args['discount_rate'] = 0.07 + args['discount_rate'] = '0.07' # pass str to test casting # Test that only grid points are provided in grid_points_path args['grid_points_path'] = os.path.join( SAMPLE_DATA, 'resampled_grid_pts.csv') args['price_table'] = False args['wind_price'] = 0.187 - args['rate_change'] = 0.2 + args['rate_change'] = '0.2' # pass str to test casting wind_energy.execute(args)