def get_optimal_mix_balancing(L, GW, GS, gamma=1., p_interval=0.01, CS=None, returnall=False, normalized=True): L, GW, GS = array(L,ndmin=2), array(GW,ndmin=2), array(GS,ndmin=2) #Ensure minimum dimension to 2 to alow the weighed sum to be calculated correctly. weighed_sum = lambda x: sum(x,axis=0)/mean(sum(x,axis=0)) l = weighed_sum(L) Gw = weighed_sum(GW) Gs = weighed_sum(GS) mismatch = lambda alpha_w: gamma*(alpha_w*Gw + (1.-alpha_w)*Gs) - l if CS==None: res_load_sum = lambda alpha_w: sum(get_positive(-mismatch(alpha_w))) else: res_load_sum = lambda alpha_w: sum(get_positive(-get_policy_2_storage(mismatch(alpha_w),storage_capacity = CS)[0])) alpha_w_opt = fmin(res_load_sum,0.5,disp=False) if alpha_w_opt>1.: alpha_w_opt = 1. elif alpha_w_opt<0.: alpha_w_opt = 0. if normalized: if CS==None: mismatch_opt = mismatch(alpha_w_opt) else: mismatch_opt = get_policy_2_storage(mismatch(alpha_w_opt),storage_capacity = CS)[0] else: if CS==None: mismatch_opt = mismatch(alpha_w_opt)*mean(sum(L,axis=0)) else: mismatch_opt = get_policy_2_storage(mismatch(alpha_w_opt),storage_capacity = CS)[0]*mean(sum(L,axis=0)) res_load_sum_opt = res_load_sum(alpha_w_opt) if returnall: res_load_sum_1p_interval = lambda alpha_w: res_load_sum(alpha_w)-(res_load_sum(alpha_w_opt)+p_interval*sum(l)) if sign(res_load_sum_1p_interval(0))!=sign(res_load_sum_1p_interval(alpha_w_opt)): lower_bound = brentq(res_load_sum_1p_interval, 0, alpha_w_opt) else: lower_bound = 0 if sign(res_load_sum_1p_interval(1))!=sign(res_load_sum_1p_interval(alpha_w_opt)): upper_bound = brentq(res_load_sum_1p_interval, alpha_w_opt, 1) else: upper_bound = 1 alpha_w_opt_1p_interval = array([lower_bound,upper_bound]) res_load_sum_1p = amax([res_load_sum(lower_bound),res_load_sum(upper_bound)]) #Returns: alpha_w_opt, alpha_w_opt_1p_interval, res_load_sum_opt, mismatch_opt return alpha_w_opt, alpha_w_opt_1p_interval, res_load_sum_opt, mismatch_opt, res_load_sum_1p else: return alpha_w_opt
def get_balancing(L, GW, GS, gamma=1, alpha=1., CS=None,returnall=False): L, GW, GS, gamma, alpha = array(L,ndmin=2), array(GW,ndmin=2), array(GS,ndmin=2), array(gamma,ndmin=1), array(alpha,ndmin=1) #Ensure minimum dimension to 2 to alow the weighed sum to be calculated correctly. weighed_sum = lambda x: sum(x,axis=0)/mean(sum(x,axis=0)) l = weighed_sum(L) Gw = weighed_sum(GW) Gs = weighed_sum(GS) mismatch = lambda alpha_w, gamma: gamma*(alpha_w*Gw + (1.-alpha_w)*Gs) - l if CS==None: res_load_sum = lambda alpha_w, gamma: sum(get_positive(-mismatch(alpha_w,gamma))) else: res_load_sum = lambda alpha_w, gamma: sum(get_positive(-get_policy_2_storage(mismatch(alpha_w,gamma),storage_capacity = CS)[0])) Gamma, Alpha = meshgrid(gamma,alpha) Res_load_sum = zeros(Gamma.shape) for i in arange(size(Gamma)): Res_load_sum.flat[i] = res_load_sum(Alpha.flat[i],Gamma.flat[i]) if returnall: return Res_load_sum, Gamma, Alpha else: return Res_load_sum
def get_compare_VRES_load(ISO='DK', gamma=0.5, alpha_w=.5, CS=None, silent=True): #Load data t, L, Gw, Gs, datetime_offset, datalabel = get_ISET_country_data(ISO) if alpha_w==None: alpha_w = get_optimal_mix_balancing(L, Gw, Gs, gamma) if ~silent: print 'Mix not specified. Optimal mix alpha_w={0} chosen'.format(alpha_w) wind = gamma*alpha_w*Gw*mean(L) solar = gamma*(1-alpha_w)*Gs*mean(L) mismatch = (wind+solar) - L if CS!=None or CS==0: mismatch_r = get_policy_2_storage(mismatch, eta_in = 1., eta_out = 1., storage_capacity = CS)[0] else: mismatch_r = mismatch curtailment = get_positive(mismatch_r) filling = get_positive(mismatch - mismatch_r) extraction = get_positive(-(mismatch - mismatch_r)) wind_local = wind - (curtailment+filling)*wind/(wind+solar+1e-10) solar_local = solar - (curtailment+filling)*solar/(wind+solar+1e-10) return L, wind_local, solar_local, curtailment, filling, extraction
def get_optimal_mix_storage(L, GW, GS, gamma=1., p_interval=0.01, returnall=False): L, GW, GS = array(L,ndmin=2), array(GW,ndmin=2), array(GS,ndmin=2) #Ensure minimum dimension to 2 to alow the weighed sum to be calculated correctly. weighed_sum = lambda x: sum(x,axis=0)/mean(sum(x,axis=0)) l = weighed_sum(L) Gw = weighed_sum(GW) Gs = weighed_sum(GS) mismatch = lambda alpha_w: gamma*(alpha_w*Gw + (1.-alpha_w)*Gs) - l E_H = lambda alpha_w: get_policy_2_storage(mismatch(alpha_w))[1] alpha_w_opt = fmin(E_H,0.5,disp=True) if returnall: balancing_fixed_E_H = lambda alpha_w: sum(get_positive(-get_policy_2_storage(mismatch(alpha_w),storage_capacity = E_H(alpha_w_opt))[0])) - p_interval*sum(l) if balancing_fixed_E_H(0)>0: if balancing_fixed_E_H(1)>0: alpha_w_opt_1p_interval = array([brentq(balancing_fixed_E_H, 0, alpha_w_opt),brentq(balancing_fixed_E_H, alpha_w_opt, 1)]) else: alpha_w_opt_1p_interval = array([brentq(balancing_fixed_E_H, 0, alpha_w_opt),1.]) else: if balancing_fixed_E_H(1)>0: alpha_w_opt_1p_interval = array([0.,brentq(balancing_fixed_E_H, alpha_w_opt, 1)]) else: alpha_w_opt_1p_interval = array([0.,1.]) print balancing_fixed_E_H(0), balancing_fixed_E_H(1) print alpha_w_opt, alpha_w_opt_1p_interval #Returns: alpha_w_opt, alpha_w_opt_1p_interval return alpha_w_opt, alpha_w_opt_1p_interval, E_H(alpha_w_opt) else: return E_H(alpha_w_opt), alpha_w_opt
def get_mismatch(L, GW, GS, gamma=1, alpha_w=1.,CS=None): L, GW, GS, gamma, alpha_w = array(L,ndmin=2), array(GW,ndmin=2), array(GS,ndmin=2), array(gamma,ndmin=1), array(alpha_w,ndmin=1) #Ensure minimum dimension to 2 to alow the weighed sum to be calculated correctly. weighed_sum = lambda x: sum(x,axis=0)/mean(sum(x,axis=0)) l = weighed_sum(L) Gw = weighed_sum(GW) Gs = weighed_sum(GS) mismatch = lambda alpha_w, gamma: gamma*(alpha_w*Gw + (1.-alpha_w)*Gs) - l if CS==None: return mismatch(alpha_w,gamma) else: return get_policy_2_storage(mismatch(alpha_w,gamma),storage_capacity = CS)[0]
def plot_monthly_summary(ISO='DK', gamma=.5, alpha_w=None, CS=None, titletxt='Denmark, 2000-2007',label='TestFigure'): #Load data t, L, Gw, Gs, datetime_offset, datalabel = get_ISET_country_data(ISO) if alpha_w==None: alpha_w = get_optimal_mix_balancing(L, Gw, Gs, gamma) print 'Mix not specified. Optimal mix alpha_w={0} chosen'.format(alpha_w) wind = gamma*alpha_w*Gw*mean(L) solar = gamma*(1-alpha_w)*Gs*mean(L) mismatch = (wind+solar) - L if CS!=None or CS==0: mismatch_r = get_policy_2_storage(mismatch, eta_in = 1., eta_out = 1., storage_capacity = CS)[0] else: mismatch_r = mismatch curtailment = get_positive(mismatch_r) filling = get_positive(mismatch - mismatch_r) extraction = get_positive(-(mismatch - mismatch_r)) wind_local = wind - (curtailment+filling)*wind/(wind+solar+1e-10) solar_local = solar - (curtailment+filling)*solar/(wind+solar+1e-10) t_month = array([d.month for d in num2date(t+datetime_offset)]) months = arange(0,12)+1 load_sum, wind_sum, solar_sum, storage_sum, curtail_sum, weight = zeros(12), zeros(12), zeros(12), zeros(12), zeros(12), zeros(12) for month in months: load_sum[month-1] = sum(L[find(t_month==month)]) wind_sum[month-1] = sum(wind_local[find(t_month==month)]) solar_sum[month-1] = sum(solar_local[find(t_month==month)]) storage_sum[month-1] = sum(extraction[find(t_month==month)]) curtail_sum[month-1] = sum(curtailment[find(t_month==month)]) weight[month-1] = len(find(t_month==month))/float(len(t)) #Set plot options matplotlib.rcParams['font.size'] = 10 close(1); figure(1); clf() gcf().set_dpi(300) gcf().set_size_inches([6.5,4.3]) #Monthly values pp_wind = bar(months,wind_sum*100/load_sum,color=color_wind) pp_solar = bar(months,solar_sum*100/load_sum,bottom=wind_sum*100/load_sum,color=color_solar) pp_storage = bar(months,storage_sum*100/load_sum,bottom=(wind_sum+solar_sum)*100/load_sum,color='g') pp_curtailment = bar(months,curtail_sum*100/load_sum,bottom=(wind_sum+solar_sum+storage_sum)*100/load_sum,color='r') pp_gross = axhline(100*gamma,color='k',ls='--',lw=1.5) #Average values bar(13.5,sum(wind_sum)*100/sum(load_sum),color=color_wind) bar(13.5,sum(solar_sum)*100/sum(load_sum),bottom=sum(wind_sum)*100/sum(load_sum),color=color_solar) bar(13.5,sum(storage_sum)*100/sum(load_sum),bottom=sum(wind_sum+solar_sum)*100/sum(load_sum),color='g') bar(13.5,sum(curtail_sum)*100/sum(load_sum),bottom=sum(wind_sum+solar_sum+storage_sum)*100/sum(load_sum),color='r') print 'Local excess: {0} pp'.format(sum(curtail_sum)*100/sum(load_sum),bottom=sum(wind_sum+solar_sum)*100/sum(load_sum)) axis(xmin=.5,xmax=14.75,ymin=0,ymax=100) month_names = array([calendar.month_abbr[m] for m in months]) xticks(concatenate([months,[13.5]]),concatenate([month_names,['Av.']]),rotation=-45,ha='left') ylabel('Percentage points (pp)') pp = [pp_gross,pp_wind[0],pp_solar[0],pp_curtailment[0]] txtlabels = ['Gross share','Wind','Solar','Local excess'] titletxt = titletxt + '\nwind/solar mix: {0}/{1}'.format(int(round(100*alpha_w)),int(round(100*(1-alpha_w)))) leg = legend(pp,txtlabels,loc='upper left',ncol=4,title=titletxt); ltext = leg.get_texts(); setp(ltext, fontsize='small') # the legend text fontsize tight_layout() save_file_name = 'plot_monthly_summary_'+ISO+'_'+label+'.pdf' save_figure(save_file_name) ### Single bar summary: close(1); figure(1); clf() gcf().set_dpi(300) gcf().set_size_inches([3,2]) ax=axes([0.03,0.03,.33,1]) #Average values bar(0,mean(wind_sum)/mean(load_sum),color=color_wind,align='center',width=1) bar(0,mean(solar_sum)/mean(load_sum),bottom=mean(wind_sum)/mean(load_sum),color=color_solar,align='center',width=1) bar(0,mean(storage_sum)/mean(load_sum),bottom=mean(wind_sum+solar_sum)/mean(load_sum),color='g',align='center',width=1) bar(0,mean(curtail_sum)/mean(load_sum),bottom=mean(wind_sum+solar_sum+storage_sum)/mean(load_sum),color='r',align='center',width=1) axis(xmin=-.75,xmax=.75,ymin=0,ymax=1.1) ax.spines['top'].set_color('none') ax.spines['right'].set_color('none') ax.spines['left'].set_color('none') ax.xaxis.set_ticks_position('none') ax.yaxis.set_ticks_position('none') ax.tick_params(labelbottom=0, labeltop=0, labelleft=0, labelright=0) if CS==None: text(0.37,0.9,'Total: {0:0.1f} GWh\nSurplus: {1:.1f}%'.format(gamma*mean(L),mean(curtail_sum)/(mean(load_sum)*gamma)*100),fontsize=10,weight='semibold',ha='left',va='top',transform = gcf().transFigure,bbox=dict(boxstyle="round, pad=.75", fc="w",lw=1.5)) else: text(0.37,0.9,'Total: {0:0.1f} GWh\nSurplus: {1:.1f}%\nStorage: -{2:.1f}%\n----------------------\nRemainder: {3:.1f}%\n\nStorage volume:\n{4:.1f} GWh'.format(gamma*mean(L),mean(curtail_sum+storage_sum)/(mean(load_sum)*gamma)*100,mean(storage_sum)/(mean(load_sum)*gamma)*100,mean(curtail_sum)/(mean(load_sum)*gamma)*100,mean(L)*CS),fontsize=10,weight='semibold',ha='left',va='top',transform = gcf().transFigure,bbox=dict(boxstyle="round, pad=.75", fc="w",lw=1.5)) #tight_layout() save_file_name = 'plot_single_bar_summary_'+ISO+'_'+label+'.pdf' save_figure(save_file_name) ### Single bar summary legend close(1); figure(1); clf() gcf().set_dpi(300) gcf().set_size_inches([6.5,1]) axis('off') pp_wind = Rectangle((0, 0), 1, 1, facecolor=color_wind) pp_solar = Rectangle((0, 0), 1, 1, facecolor=color_solar) pp_curtailment = Rectangle((0, 0), 1, 1, facecolor='r') pp_storage = Rectangle((0, 0), 1, 1, facecolor='g') pp = [pp_wind,pp_solar,pp_storage,pp_curtailment] txtlabels = ['Wind','Solar','Storage','Surplus/Remainder'] leg = legend(pp,txtlabels,loc='upper left',ncol=4,frameon=False); ltext = leg.get_texts(); setp(ltext, fontsize='small') # the legend text fontsize save_file_name = 'plot_single_bar_summary_legend.pdf' save_figure(save_file_name)
def plot_hourly_generation_alt(ISO='DK', gamma=0.5, alpha_w=.5, CS=None, date_start=datestr2num('1-1-2000'), N_days=30, monday_offset=5, titletxt='Denmark, Jan. 2000', label='TestFigure'): #Load data t, L, Gw, Gs, datetime_offset, datalabel = get_ISET_country_data(ISO) mask = find((t+datetime_offset>=date_start)*(t+datetime_offset<=date_start+N_days)) if alpha_w==None: alpha_w = get_optimal_mix_balancing(L, Gw, Gs, gamma) print 'Mix not specified. Optimal mix alpha_w={0} chosen'.format(alpha_w) wind = gamma*alpha_w*Gw*mean(L) solar = gamma*(1-alpha_w)*Gs*mean(L) mismatch = (wind+solar) - L if CS!=None or CS==0: mismatch_r = get_policy_2_storage(mismatch, eta_in = 1., eta_out = 1., storage_capacity = CS)[0] else: mismatch_r = mismatch curtailment = get_positive(mismatch_r) filling = get_positive(mismatch - mismatch_r) extraction = get_positive(-(mismatch - mismatch_r)) wind_local = wind - (curtailment+filling)*wind/(wind+solar+1e-10) solar_local = solar - (curtailment+filling)*solar/(wind+solar+1e-10) #Set plot options matplotlib.rcParams['font.size'] = 10 close(1); figure(1); clf() gcf().set_dpi(300) gcf().set_size_inches([6.5,4.3]) fill_between(t[mask],wind_local[mask],color=color_wind,edgecolor=color_edge,lw=1) fill_between(t[mask],wind_local[mask]+solar_local[mask],wind_local[mask],color=color_solar,edgecolor=color_edge,lw=1) p = fill_between(t[mask],wind_local[mask]+solar_local[mask]+filling[mask],wind_local[mask]+solar_local[mask],color='g',edgecolor=color_edge,lw=1) fill_between(t[mask],wind_local[mask]+solar_local[mask]+extraction[mask],wind_local[mask]+solar_local[mask],color='g',edgecolor=color_edge,lw=1) fill_between(t[mask],wind_local[mask]+solar_local[mask]+filling[mask]+curtailment[mask],wind_local[mask]+solar_local[mask]+filling[mask],color='r',edgecolor=color_edge,lw=1) p.set_facecolors("none") from matplotlib.patches import PathPatch for path in p.get_paths(): p1 = PathPatch(path, fc="none", hatch="/") gca().add_patch(p1) p1.set_zorder(p.get_zorder()-0.1) pp_wind = Rectangle((0, 0), 1, 1, facecolor=color_wind) pp_solar = Rectangle((0, 0), 1, 1, facecolor=color_solar) pp_curtailment = Rectangle((0, 0), 1, 1, facecolor='r') pp_storage = Rectangle((0, 0), 1, 1, facecolor='g') pp_filling = Rectangle((0, 0), 1, 1, facecolor='none', hatch="/") pp_load = plot(t[mask],L[mask],color='k',lw=1.5) axis(xmin=t[mask[0]],xmax=t[mask[-1]],ymin=0,ymax=1.9*mean(L)) ylabel('Power [GW]') day_names = array([calendar.day_abbr[mod(i,7)] for i in arange(N_days)+monday_offset]) #day_names[find([d!='Mon' for d in day_names])] = '' xticks(t[mask[0]]+arange(N_days),day_names,rotation=-45,ha='left') if CS==None: pp = [pp_load[0],pp_wind,pp_solar,pp_curtailment] txtlabels = ['Load ({0})'.format(ISO),'Wind','Solar','Surplus'] leg = legend(pp,txtlabels,loc='upper left',ncol=5,title=titletxt); else: pp = [pp_load[0],pp_filling,pp_wind,pp_curtailment,pp_solar,pp_storage] txtlabels = ['Load ({0})'.format(ISO),'Stored surplus','Wind','Remainder surplus','Solar','Storage'] leg = legend(pp,txtlabels,loc='upper left',ncol=4,title=titletxt); ltext = leg.get_texts(); setp(ltext, fontsize='small') # the legend text fontsize tight_layout() save_file_name = 'plot_hourly_generation_alt_'+ISO+'_'+label+'.pdf' save_figure(save_file_name)