def main(heat_density_map, pix_threshold, DH_threshold, output_raster1, output_raster2, output_shp1, output_shp2, in_orig=None, only_return_areas=False): # DH_Regions: boolean array showing DH regions DH_Regions, hdm_dh_region_cut, geo_transform, total_heat_demand = DHP.DHReg(heat_density_map, pix_threshold, DH_threshold, in_orig) if only_return_areas: geo_transform = None return DH_Regions DHPot, labels = DHP.DHPotential(DH_Regions, heat_density_map) total_potential = np.around(np.sum(DHPot),2) total_heat_demand = np.around(total_heat_demand, 2) if total_potential == 0: dh_area_flag = False else: dh_area_flag = True graphics = [ { "type": "bar", "xLabel": "DH Area Label", "yLabel": "Potential (GWh/year)", "data": { "labels": [str(x) for x in range(1, 1+len(DHPot))], "datasets": [{ "label": "Potential in coherent areas", "backgroundColor": ["#3e95cd"]*len(DHPot), "data": list(np.around(DHPot,2)) }] } },{ "type": "bar", "xLabel": "", "yLabel": "Demand / Potential (GWh/year)", "data": { "labels": ["Annual heat demand", "DH potential"], "datasets": [{ "label": "Heat Demand Vs. DH Potential (GWh/year)", "backgroundColor": ["#fe7c60", "#3e95cd"], "data": [total_heat_demand, total_potential] }] } }] symbol_vals_str = [] if dh_area_flag: CM19.main(output_raster1, geo_transform, 'int8', DH_Regions) temp_raster = os.path.dirname(output_raster2) + '/temp.tif' CM19.main(temp_raster, geo_transform, 'int32', labels) symbol_vals_str = polygonize(output_raster1, temp_raster, output_shp1, output_shp2, DHPot) rm_file(temp_raster, temp_raster[:-4] + '.tfw') CM19.main(output_raster2, geo_transform, 'float32', hdm_dh_region_cut) return total_potential, total_heat_demand, graphics, symbol_vals_str
def raster_cut(raster_path, features_path, output_dir, cut_name): shpName = features_path.replace('\\', '/') shpName = shpName.split('/')[-1][0:-4] raster_cut_old = output_dir + os.sep + shpName + '_feature_0.tif' raster_cut_new = output_dir + os.sep + cut_name + '.tif' rm_file(raster_cut_old, raster_cut_new) array, gt = RAbF(features_path, raster_path, return_gt=True) CM22.main(array, features_path, output_dir, gt, nodata=0, save2raster=True) os.rename(raster_cut_old, raster_cut_new) os.rename(raster_cut_old[:-3] + 'tfw', raster_cut_new[:-3] + 'tfw') return raster_cut_new
def scaling(hdm_cut, hdm_cut_gt, updated_demand, outRasterPath): ''' This module gets a demand value and uses the default distribution of heat density map for distributing this value between pixels. The module returns a numpy array. hdm_cut: numpy array showing demand in MWh/ha hdm_cut_gt: raster geo-transform updated_demand: in GWh/a outRasterPath: path for saving the updated hdm ''' # Sum over pixel values in MWh/ha and return in GWh sum_demand_cut = np.sum(hdm_cut) * 0.001 new_HDM_cut = updated_demand / sum_demand_cut * hdm_cut rm_file(outRasterPath) CM19.main(outRasterPath, hdm_cut_gt, "float32", new_HDM_cut) return outRasterPath
def distribuition_costs(pixT, DH_threshold, dist_grid_cost, out_raster_hdm_last_year, out_raster_maxDHdem, out_raster_invest_Euro, out_raster_coh_area_bool, out_raster_labels, struct=np.ones((3, 3))): rm_file(out_raster_coh_area_bool, out_raster_labels) invest_Euro_arr = raster_array(out_raster_invest_Euro) maxDHdem_arr = raster_array(out_raster_maxDHdem) heat_density_map_last_year, geo_transform = raster_array( out_raster_hdm_last_year, return_gt=True) rast_origin = geo_transform[0], geo_transform[3] coh_areas = np.zeros_like(maxDHdem_arr, 'int8') reg_filter = maxDHdem_arr.astype(bool).astype('int8') # DH_threshold in MWH DH_threshold_MWh = DH_threshold * 1000 for pix_threshold in pixT: # calculate coherent regions with given thresholds and cut them to # LAU2 levels # DH_Regions: boolean array showing DH regions DH_Regions, gt = DHP.DHReg(heat_density_map_last_year, pix_threshold, DH_threshold, rast_origin) # multiplication with reg_filter required to follow out_raster_maxDHdem # pattern and separate connection of regions with pixels that have # value of zero in out_raster_maxDHdem result = DH_Regions.astype(int) * reg_filter labels, nr_coherent = measurements.label(result, structure=struct) if nr_coherent == 0: break for i in range(1, nr_coherent + 1): temp = labels == i q = np.sum(maxDHdem_arr[temp]) q_inv = np.sum(invest_Euro_arr[temp]) q_spec_cost = q_inv / q if q_spec_cost <= dist_grid_cost and q >= DH_threshold_MWh: coh_areas[temp] = 1 heat_density_map_last_year[temp] = 0 labels = None nr_coherent = None labels, numLabels = measurements.label(coh_areas, structure=struct) CM19.main(out_raster_coh_area_bool, geo_transform, 'int8', coh_areas) CM19.main(out_raster_labels, geo_transform, "int16", labels) return numLabels
def dh_demand(c1, c2, raster_plotratio, raster_hdm, start_year, last_year, accumulated_energy_saving, dh_connection_rate_1st_year, dh_connection_rate_last_year, depr_period, output_dir, interest, output_layers, dA_slope=0.0486, dA_intercept=0.0007, dataType='float32'): ''' Important Note: 1) Here, for the calculation of plot ratio, I used gross floor area raster in one hectar resolution (unit: m2). It should be divided by 1e4 to get the plot ratio. 2) if you have plot ratio raster, remove the 1e4 factor. 3) Distribution cost is calculated for those pixel that their corresponding pipe diameter is equal or greater than 0. the input heat density map should be in GWh/km2. ''' horizon = last_year - start_year + 1 if horizon > depr_period: raise Warning('Study horizon is longer than depr_period of district. ' 'The calculation will be done only till the end of ' 'depr_period!') horizon = depr_period remaining_years = 0 else: remaining_years = depr_period - horizon energy_reduction_factor = (1 - accumulated_energy_saving)**(1 / (horizon - 1)) hdm_ds = gdal.Open(raster_hdm) hdm_band = hdm_ds.GetRasterBand(1) hdm = hdm_band.ReadAsArray().astype(float) geo_transform = hdm_ds.GetGeoTransform() plotRatio_ds = gdal.Open(raster_plotratio) plotRatio_band = plotRatio_ds.GetRasterBand(1) # gfa in hectar should be devided by 10000 to get right values for # plot ratio (m2/m2). plotRatio = plotRatio_band.ReadAsArray().astype(float) / 10000.0 hdm_ds = plotRatio_ds = None row, col = np.nonzero( (hdm > 0).astype(int) * (plotRatio > 0.0).astype(int)) # unit conversion from MWh/ha to GJ/m2 sparseDemand = 0.00036 * hdm[row, col] PR_sparse = plotRatio[row, col] # the unit for L is m/m2 # L is in m/m2: to get the value for each pixel (ha) you should multiply it # by 10000 because 1 pixel has 10000 m2 L = 1 / (61.8 * PR_sparse**(-0.15)) # initialize the variables q = 0 # q_new = dh_connection_rate_1st_year * sparseDemand q_tot = np.copy(sparseDemand) q_max = np.zeros_like(q_tot) for i in range(horizon): q_tot = sparseDemand * energy_reduction_factor**i q_new = q_tot * ( dh_connection_rate_1st_year + i * (dh_connection_rate_last_year - dh_connection_rate_1st_year) / (horizon - 1)) # q_new is a non-zero sparse matrix. The development of demand can be # checked by comparing just one element of q_new with q_max. if q_new[0] > q_max[0]: q_max = np.copy(q_new) q += q_new / (1 + interest)**i if remaining_years > 0: alpha_horizon = annuity(interest, horizon - 1) alpha_depr = annuity(interest, depr_period) rest_annuity_factor = alpha_depr - alpha_horizon q = q + q_new * rest_annuity_factor linearHeatDensity = q_max / L # this step is performed to avoid negative effective pipe diameter LHD_THRESHOLD = -dA_intercept / dA_slope filtered_LHD = (np.log(linearHeatDensity) < LHD_THRESHOLD).astype(int) elements = np.nonzero(filtered_LHD)[0] dA = dA_slope * (np.log(linearHeatDensity)) + dA_slope cf1, cf2 = cost_factors(c1, c2, PR_sparse) dA[elements] = 0 q_max[elements] = 0 denominator = q / L divisor = cf1[1] + cf2[1] * dA divisor[elements] = 0 investment = divisor / denominator finalInvestment = np.zeros_like(hdm, dtype=dataType) # from Euro/GJ/m2 to Euro/MWh/m2 finalInvestment[row, col] = investment * 3.6 maxDHdem_arr = np.zeros_like(finalInvestment, dtype=dataType) # max DH demand density in MWh within the study horizon maxDHdem_arr[row, col] = q_max * 10000 / 3.6 invest_Euro_arr = maxDHdem_arr * finalInvestment hdm_last_year = np.zeros_like(finalInvestment, dtype=dataType) # total demand in the last year of study horizon in MWh/ha hdm_last_year[row, col] = q_tot * 10000 / 3.6 # total demand in last year in GWh for pixels with Plot Ration > 0 last_year_dem = np.sum(hdm_last_year) / 1000 # Length of pipes (L) length = np.zeros_like(finalInvestment, dtype=dataType) length[row, col] = L length[row, col][elements] = 0 maxDHdem, invest_Euro, hdm_cut_last_year, total_pipe_length = output_layers rm_file(maxDHdem, invest_Euro, hdm_cut_last_year, total_pipe_length) CM19.main(maxDHdem, geo_transform, dataType, maxDHdem_arr) CM19.main(invest_Euro, geo_transform, dataType, invest_Euro_arr) CM19.main(hdm_cut_last_year, geo_transform, dataType, hdm_last_year) CM19.main(total_pipe_length, geo_transform, dataType, length) # sum(MWh/ha) and convert to GWh first_year_dem_all = np.sum(hdm) / 1000 # demand in GWh for pixels with Plot Ratio > 0 first_year_dem = np.sum(sparseDemand) * 10000 / 3600 return first_year_dem_all, first_year_dem, last_year_dem
def distribuition_costs(invest_Euro, maxDHdem, features_path, hdm_1st, hdm_last, MS_1st, pixT, DHT, costT, coh_area_raster, hdm_dh_reg_last_year, label_raster, struct=np.ones((3, 3))): rm_file(coh_area_raster, hdm_dh_reg_last_year, label_raster) invest_Euro_arr = raster_array(invest_Euro) maxDHdem_arr = raster_array(maxDHdem) hdm_arr, geo_transform = raster_array(hdm_last, return_gt=True) rast_origin = geo_transform[0], geo_transform[3] coh_areas = np.zeros_like(maxDHdem_arr, 'int8') reg_filter = maxDHdem_arr.astype(bool).astype('int8') for pix_threshold in pixT: # calculate coherent regions with given thresholds and cut them to # LAU2 levels DH_Regions = CM4.main(hdm_arr, features_path, pix_threshold, DHT, None, rast_origin, only_return_areas=True) # multiplication with reg_filter required to follow maxDHdem # pattern and separate connection of regions with pixels that have # value of zero in maxDHdem result = DH_Regions.astype(int) * reg_filter labels, nr_coherent = measurements.label(result, structure=struct) if nr_coherent == 0: break for i in range(1, nr_coherent + 1): temp = labels == i q = np.sum(maxDHdem_arr[temp]) q_inv = np.sum(invest_Euro_arr[temp]) q_spec_cost = q_inv / q if q_spec_cost <= costT and q >= DHT: coh_areas[temp] = 1 hdm_arr[temp] = 0 labels = None nr_coherent = None hdm_last_arr = raster_array(hdm_last) hdm_1st_arr = raster_array(hdm_1st) labels, numLabels = measurements.label(coh_areas, structure=struct) if numLabels == 0: raise ValueError('For the provided grid cost ceiling, no district ' 'heating potential area can be realized!') if numLabels > 100: raise ValueError('For the given scenario, we found more than 100 ' 'coherent areas. Please reduce the size of your ' 'selection and run the scenario again!') hdm_in_dh_reg = hdm_last_arr * coh_areas CM19.main(coh_area_raster, geo_transform, 'int8', coh_areas) CM19.main(hdm_dh_reg_last_year, geo_transform, "float64", hdm_in_dh_reg) CM19.main(label_raster, geo_transform, "int16", labels) # average demand in dh regions: sum_demand/sum_area_of_dhReg # MWh/ha ave_dem_dh_reg = np.sum(hdm_in_dh_reg) / np.sum(coh_areas)
def dh_demand(c1, c2, raster_plotratio, raster_hdm, start_year, last_year, accumulated_energy_saving, dh_connection_rate_1st_year, dh_connection_rate_last_year, depr_period, interest, output_layers, dA_slope=0.0486, dA_intercept=0.0007, dataType='float32'): ''' Important Note: 1) Here, for the calculation of plot ratio, I used gross floor area raster in one hectar resolution (unit: m2). It should be divided by 1e4 to get the plot ratio. 2) if you have plot ratio raster, remove the 1e4 factor. 3) Distribution cost is calculated for those pixel that their corresponding pipe diameter is equal or greater than 0. the input heat density map should be in GWh/km2. ''' horizon = int(last_year) - int(start_year) + 1 horizon = int(horizon) if horizon > int(depr_period): horizon = depr_period remaining_years = 0 else: remaining_years = int(depr_period) - int(horizon) energy_reduction_factor = (1-float(accumulated_energy_saving))**(1/(horizon-1)) hdm_ds = gdal.Open(raster_hdm) hdm_band = hdm_ds.GetRasterBand(1) hdm = hdm_band.ReadAsArray().astype(float) geo_transform = hdm_ds.GetGeoTransform() plotRatio_ds = gdal.Open(raster_plotratio) plotRatio_band = plotRatio_ds.GetRasterBand(1) # gfa in hectar should be devided by 10000 to get right values for # plot ratio (m2/m2). plotRatio = plotRatio_band.ReadAsArray().astype(float)/10000.0 hdm_ds = plotRatio_ds = None row, col = np.nonzero((hdm > 0).astype(int) * (plotRatio > 0.0).astype(int)) # unit conversion from MWh/ha to GJ/m2 sparseDemand = 0.00036*hdm[row, col] PR_sparse = plotRatio[row, col] # the unit for L is m however in each m2 # L is in m: to get the value for each pixel (ha) you should multiply it # by 10000 because 1 pixel has 10000 m2 # The following formulation of L comes from Persson et al. 2019 paper with # the title "Heat Roadmap Europe: Heat distribution costs" L = 1 / ((PR_sparse <= 0.4).astype(int) * (137.5*PR_sparse + 5) + (PR_sparse > 0.4).astype(int) * 60) # initialize the variables q = 0 # q_new = dh_connection_rate_1st_year * sparseDemand q_tot = np.copy(sparseDemand) q_max = np.zeros_like(q_tot) for i in range(horizon): q_tot = sparseDemand * energy_reduction_factor**i q_new = q_tot * (float(dh_connection_rate_1st_year) + i * (float(dh_connection_rate_last_year) - float(dh_connection_rate_1st_year))/(horizon-1)) # q_new is a non-zero sparse matrix. The development of demand can be # checked by comparing just one element of q_new with q_max. if q_new[0] > q_max[0]: q_max = np.copy(q_new) q += q_new / (1 + float(interest))**i if remaining_years > 0: if interest > 0: alpha_horizon = annuity(interest, horizon-1) alpha_depr = annuity(interest, depr_period) rest_annuity_factor = alpha_depr - alpha_horizon q = q + q_new * rest_annuity_factor else: q = q + q_new * remaining_years linearHeatDensity = q_max / L # this step is performed to avoid negative average pipe diameter LHD_THRESHOLD = -dA_intercept/dA_slope filtered_LHD = (np.log(linearHeatDensity) < LHD_THRESHOLD).astype(int) elements = np.nonzero(filtered_LHD)[0] dA = dA_slope * (np.log(linearHeatDensity)) + dA_slope dA[elements] = 0 # lower limit of linear heat densities at 1.5 GJ/m was set. Below this # threshold, pipe diameters of 0.02m were applied uniformly for all hectare # grid cells with present heat density values above zero. # Note: linearHeatDensity is calculated for cells with heat demand above zero dA[((linearHeatDensity < 1.5).astype(int) * (dA > 0).astype(int)).astype(bool)] = 0.02 q_max[elements] = 0 denominator = q / L """ # old code cf1, cf2 = cost_factors(c1, c2, PR_sparse) divisor = cf1[1] + cf2[1]*dA """ divisor = c1 + c2*dA divisor[elements] = 0 investment = divisor/denominator finalInvestment = np.zeros_like(hdm, dtype=dataType) # from Euro/GJ/m2 to Euro/MWh/m2 finalInvestment[row, col] = investment*3.6 maxDHdem_arr = np.zeros_like(finalInvestment, dtype=dataType) # max DH demand density in MWh within the study horizon maxDHdem_arr[row, col] = q_max*10000/3.6 invest_Euro_arr = maxDHdem_arr * finalInvestment hdm_last_year = np.zeros_like(finalInvestment, dtype=dataType) # total demand in the last year of study horizon in MWh/ha hdm_last_year[row, col] = q_tot*10000/3.6 # Length of pipes (L) length = np.zeros_like(finalInvestment, dtype=dataType) length[row, col] = L length[row, col][elements] = 0 maxDHdem, invest_Euro, hdm_cut_last_year, total_pipe_length = output_layers rm_file(maxDHdem, invest_Euro, hdm_cut_last_year, total_pipe_length) CM19.main(maxDHdem, geo_transform, dataType, maxDHdem_arr) CM19.main(invest_Euro, geo_transform, dataType, invest_Euro_arr) CM19.main(hdm_cut_last_year, geo_transform, dataType, hdm_last_year) CM19.main(total_pipe_length, geo_transform, dataType, length) """