예제 #1
0
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
예제 #2
0
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
예제 #3
0
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
예제 #4
0
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
예제 #5
0
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]
예제 #6
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)
예제 #7
0
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)