Example #1
0
    def __init__(self,
                 COP=None,
                 max_capacity=None,
                 Qmax=None,
                 taxation=None,
                 investment_cost=None,
                 **kwargs):
        super().__init__(**kwargs)

        with fs.namespace(self):
            Q = fs.VariableCollection(lb=0, ub=Qmax, name='Q')
            inv = fs.Variable(domain=fs.Domain.binary)

        self.production[Resources.heat] = Q
        self.consumption[Resources.power] = lambda t: Q(t) / COP
        #power_cons_tax = taxation('consumption', Resources.power)
        #Instead of using power_cons_tax in the lambda function I added 10 as a fixed cost
        self.cost = lambda t: self.consumption[Resources.power](t) * 10
        self.state_variables = lambda t: {Q(t)}
        self.inv = inv

        if max_capacity:
            self.max_capacity = max_capacity
            self.constraints += self.max_production
            self.investment_cost = inv * investment_cost
            self.static_variables = {inv}
        else:
            self.static_variables = {}
Example #2
0
    def __init__(self,
                 G=None,
                 T=None,
                 max_capacity=None,
                 capacity=None,
                 taxation=None,
                 running_cost=0,
                 investment_cost=None,
                 **kwargs):
        super().__init__(**kwargs)

        self.test = {
            'max_capacity': max_capacity,
            'capacity': capacity,
            'taxation': taxation,
            'investment_cost': investment_cost
        }

        c1 = -0.0177162
        c2 = -0.040289
        c3 = -0.004681
        c4 = 0.000148
        c5 = 0.000169
        c6 = 0.000005

        Gstc = 1
        Tstc = 25
        coef_temp_PV = 0.035

        if max_capacity:
            PV_cap = fs.Variable(lb=0, ub=max_capacity, name='PV_cap')
            self.PV_cap = PV_cap
            self.investment_cost = PV_cap * investment_cost
            self.static_variables = {PV_cap}
        else:
            PV_cap = capacity
            self.PV_cap = PV_cap
        print('!! -- PV PROD IS NOT DEFINED CORRECTLY -- !!')

        def prod(t):
            if G[t] == 0:
                prod = PV_cap * 0
            else:
                G[t] = abs(G[t] / (Gstc * 1000))
                T[t] = (T[t] + coef_temp_PV * G[t]) - Tstc
                prod = PV_cap * 35  #PV_cap* (G[t]*(1 + c1*math.log10(G[t]) + c2*(math.log10(G[t]))**2 + c3*T[t] + c4*T[t]*math.log10(G[t]) + c5*T[t]*(math.log10(G[t]))**2 + c6*(T[t])**2))
            return prod

        self.cost = lambda t: 0
        self.production[Resources.power] = lambda t: prod(t)
        self.state_variables = lambda t: {}
Example #3
0
    def __init__(self,
                 resource=None,
                 max_flow=0,
                 max_energy=0,
                 loss_factor=0,
                 max_capacity=None,
                 investment_cost=None,
                 t_start='2016-01-01',
                 t_end='2016-01-02',
                 **kwargs):
        super().__init__(**kwargs)
        with fs.namespace(self):
            volume = fs.VariableCollection(lb=0, ub=max_energy, name='Storage')
            #cap = fs.Variable(lb=0, ub=max_capacity, name='cap')
            inv = fs.Variable(domain=fs.Domain.binary)

        self.test = {
            'resource': resource,
            'max_flow': max_flow,
            'max_energy': max_energy,
            'loss_factor': loss_factor,
            'max_capacity': max_capacity,
            'investment_cost': investment_cost
        }

        self.t_start = t_start
        self.t_end = t_end
        self.max_energy = max_energy
        self.volume = volume
        self.resource = resource
        self.consumption[self.resource] = lambda t: loss_factor * volume(t)
        self.max_flow = max_flow
        self.cost = lambda t: 0
        self.state_variables = lambda t: {volume(t)}

        self.accumulation[self.resource] = self.compute_accumulation
        self.constraints += self.max_change_constraints
        self.inv = inv

        if max_capacity:
            self.max_capacity = max_capacity
            self.investment_cost = inv * investment_cost
            self.constraints += self.max_volume
            self.timeindependent_constraint = fs.Eq(inv, 0)
            self.static_variables = {inv}
        else:
            self.static_variables = {}

        self.constraints += self.start_end_volume
        self.constraints += self.start_volume
Example #4
0
    def __init__(self,
                 fuel=None,
                 alpha=None,
                 eta=None,
                 Fmax=None,
                 taxation=None,
                 investment_cost=None,
                 running_cost=0,
                 max_capacity=None,
                 **kwargs):
        super().__init__(**kwargs)
        try:
            if math.isnan(Fmax):
                Fmax = max_capacity
        except TypeError:
            import pdb
            pdb.set_trace()

        with fs.namespace(self):
            F = fs.VariableCollection(lb=0, ub=Fmax, name='F')
            inv = fs.Variable(domain=fs.Domain.binary, name='inv_chp')

        self.test = {
            'fuel': fuel,
            'alpha': alpha,
            'eta': eta,
            'Fmax': Fmax,
            'max_capacity': max_capacity,
            'taxation': taxation,
            'investment_cost': investment_cost
        }

        self.consumption[fuel] = F
        self.production[Resources.heat] = lambda t: F(t) * eta / (alpha + 1)
        self.production[
            Resources.power] = lambda t: alpha * F(t) * eta / (alpha + 1)
        self.cost = lambda t: F(
            t) * running_cost  #_CHP_cost_func(self, taxation, fuel)

        self.state_variables = lambda t: {F(t)}
        self.inv = inv

        if max_capacity:
            self.max_capacity = max_capacity
            self.constraints += self.max_production
            self.investment_cost = inv * investment_cost
            self.static_variables = {inv}
        else:
            self.static_variables = {}
Example #5
0
    def __init__(self,
                 fuel=None,
                 taxation=None,
                 Fmax=None,
                 eta=None,
                 investment_cost=None,
                 running_cost=0,
                 max_capacity=None,
                 **kwargs):
        super().__init__(**kwargs)

        with fs.namespace(self):
            F = fs.VariableCollection(lb=0, ub=Fmax, name='F')
            inv = fs.Variable(domain=fs.Domain.binary)

        self.test = {
            'Fmax': Fmax,
            'eta': eta,
            'running_cost': running_cost,
            'max_capacity': max_capacity
        }

        self.consumption[fuel] = F
        self.production[Resources.heat] = lambda t: eta * F(t)
        self.cost = lambda t: self.consumption[fuel](t) * running_cost

        self.state_variables = lambda t: {F(t)}
        self.inv = inv

        if max_capacity:
            self.max_capacity = max_capacity
            self.constraints += self.max_production
            self.investment_cost = inv * investment_cost
            self.static_variables = {inv}
        else:
            self.static_variables = {}
Example #6
0
def test_simple_SOS1():
    n = 4
    index = 2
    sum_val = 3.
    vs = [fs.Variable(lb=-1, domain=fs.Domain.integer) for i in range(n)]
    #vs[0] = fs.Variable(lb=-1, domain=fs.Domain.integer)
    weights = [1 for i in range(n)]
    weights[index] = 0.5
    prob = fs.Problem()
    prob.add_constraint(fs.SOS1(vs))
    prob.add_constraint(Constraint(sum(vs) == sum_val))
    #prob.constraints.update(Constraint(v >= 0) for v in vs)
    prob.objective = fs.Minimize(sum(v * w for v, w in zip(vs, weights)))

    solution = default_solver.solve(prob)
    print(solution)
    for v in vs:
        v.take_value(solution)

    for i in range(n):
        if i == index:
            assert (approx(vs[i].value, sum_val))
        else:
            assert (approx(vs[i].value, 0))
Example #7
0
    def make_parts(self, parameters):
        def make_tax_function(*args, **kwargs):
            def tax_function(*args, **kwargs):
                return 0
            return  tax_function

        parts = set()
        taxation = make_tax_function(parameters)
        heat_history = self.get_heat_history(parameters['time_unit'])
        power_demand = self.get_power_demand(parameters['time_unit'])
        heat_history_industry = self.get_heat_history_industry(parameters['time_unit'])
        
        for r in pl.Resources:
            if r not in [pl.Resources.heat, pl.Resources.CO2]:
                parts.add(
                    pl.Import(
                        resource=r,
                        price=parameters['prices'][r],
                        name='Import({})'.format(r),
                        CO2_factor=parameters['CO2_factor'][r]))
        
        # Conversion factor from hour to model time unit:
        # "hour" is the number of model time steps per hour.
        # So when capacities/consumption/etc per time step in plants below
        # are stated like 600 / hour", then think "600 MWh per hour".
        # Makes sense because larger time unit --> smaller value of "hour" -->
        # larger max output per time step.
        hour = pd.Timedelta('1h') / parameters['time_unit']

        print('!! -- INCORRECT RENOVATION DATA -- !!')
        renovation_data_1 = self.get_heat_history(parameters['time_unit'])*0.01 #change to renovation data when available
        renovation_data_15 =self.get_heat_history(parameters['time_unit'])*0.015 #change to renovation data when available

        if not 'Trade_off' in scenario:
            renovation = fs.Node(name = input_data['Renovation']['name'])
            renovation.consumption[pl.Resources.heat]= lambda t: -renovation_data_1['DH'][t]
            renovation.state_variables = lambda t: ()
            renovation.cost = lambda t: 0
            parts.add(renovation)

        else:
            
            print('!! -- THIS PART NEEDS CLEANING  -- !!')
            renovation = fs.Node(name = input_data['Renovation']['name'])
            inv_1 = fs.Variable(name= 'inv_1', domain = fs.Domain.binary)
            inv_0 = fs.Variable(name= 'inv_0', domain = fs.Domain.binary)
            renovation.test = {'investment_cost' : self.annuity(parameters['interest_rate'],input_data['Renovation']['lifespan'],input_data['Renovation']['investment_cost']), 'renovation level': input_data['Renovation']['capacity']}
            renovation.state_variables = lambda t: {}
            renovation.static_variables = {inv_1}#!AK, inv_0}

            renovation.consumption[pl.Resources.heat]= lambda t: - renovation_data_1['Other'][t]*inv_1 #!AK- 0*inv_0

            renovation.investment_cost =  self.annuity(parameters['interest_rate'],input_data['Renovation']['lifespan'],input_data['Renovation']['investment_cost']) * inv_1 + 0 * inv_0
            renovation.cost = lambda t:0
            parts.add(renovation)
            
            renovation_15 = fs.Node(name = input_data['Renovation_15']['name'])
            inv_15 = fs.Variable(name = 'inv_15', domain = fs.Domain.binary)
            inv_2 = fs.Variable(name = 'inv_2', domain = fs.Domain.binary)
            renovation_15.test = {'investment_cost' : self.annuity(parameters['interest_rate'],input_data['Renovation_15']['lifespan'],input_data['Renovation_15']['investment_cost']), 'renovation level': input_data['Renovation_15']['capacity']}
            renovation_15.state_variables = lambda t: {}
            renovation_15.static_variables ={inv_15}#!AK, inv_2}

            renovation_15.consumption[pl.Resources.heat]= lambda t: - renovation_data_15['DH'][t]*inv_15 #!AK - 0*inv_2

            renovation_15.investment_cost =  self.annuity(parameters['interest_rate'],input_data['Renovation_15']['lifespan'],input_data['Renovation_15']['investment_cost']) * inv_15 #!AK+ 0 * inv_2
            renovation_15.cost = lambda t:0
            parts.add(renovation_15)
            
            #renovation_const = fs.Eq(inv_0 + inv_1, 1)
            #renovation_const_2 = fs.Eq(inv_1 + inv_2 + inv_15, 1)
            
        print('!! -- INCORRECT HEAT HISTORY DATA AND NO CHANGE IN MAX_DH -- !!')
        city = fs.Node(name='City')
        city.cost = lambda t: 0
        city.state_variables = lambda t: {}

        if scenario in 'Max_DH':
            city.consumption[pl.Resources.heat] =  lambda t: heat_history['DH'][t]
        else:
            city.consumption[pl.Resources.heat] =  lambda t: heat_history['DH'][t]

        print('!! -- INCORRECT POWER DEMAND -- !!')
        city.consumption[pl.Resources.power] = lambda t: 15 #power_demand['Power demand'][t]
        parts.add(city) 

        Industry = fs.Node(name='Industry')
        Industry.consumption[pl.Resources.heat] = lambda t: heat_history_industry['DH'][t] 
        Industry.cost = lambda t: 0
        Industry.state_variables = lambda t: {}
        parts.add(Industry)

        print('!! -- POWER EXPORT WAS DIVIDED BY 10, CHANGED TO 2, WHAT IS CORRECT? -- !!')
        powerExport = pl.Export(resource = pl.Resources.power,
                                price = parameters['prices'][pl.Resources.power]/2,
                                name='power export')
        parts.add(powerExport)
        
        CO2 = pl.Export(resource = pl.Resources.CO2,
                        price = 0,
                        name = 'CO2_emissions')
        CO2.time_unit = parameters['time_unit']
        parts.add(CO2)

        "Timeindependent constraint on maximum CO2 emissions during the whole timeperiod"
        times = CO2.times_between(parameters['t_start'], parameters['t_end'])
        emissions = fs.Sum(CO2.consumption[pl.Resources.CO2](t) for t in times)
        CO2_maximum = fs.LessEqual(emissions, 100000000000) #below 24 069 146 limit the CO2 emissions
        
        print('!! -- DECREASE HEATING CONSUMPTION AS DH IS EXPANDED -- !!')
        heating = fs.Node(name='Heating') #se till att heat_history['Other'] minskar när DH byggs ut och blir större
        heating.consumption[pl.Resources.natural_gas] = lambda t: heat_history['Other'][t]*0.8/0.95 #verkningsgrad gasuppvärmning
        heating.consumption[pl.Resources.power] = lambda t: 10 #heat_history['Other'][t]*0.2/0.97  #verkningsgrad eluppvärmning
        heating.cost = lambda t: 0
        heating.state_variables = lambda t: {}
        parts.add(heating)

        CHP_A = pl.LinearCHP(name='Existing CHP A', eta=0.776, alpha=0.98, Fmax= 4.27 / hour, fuel=pl.Resources.natural_gas, taxation=taxation)
        # Fmin= 2.33 / hour, start_steps=int(np.round(.5 * hour)), 
        parts.add(CHP_A)        

        CHP_B =pl.LinearCHP(name='Existing CHP B', eta=0.778, alpha=0.98, Fmax= 4.27 /hour, fuel=pl.Resources.natural_gas, taxation=taxation)
        # Fmin= 2.33 / hour, start_steps=int(np.round(.5 * hour)),
        parts.add(CHP_B) 

        parts.add(pl.Boiler(name='Existing Boiler A', eta=0.9, Fmax=8.84 / hour, fuel=pl.Resources.natural_gas, taxation=taxation))

        parts.add(pl.Boiler(name='Existing Boiler B',eta=0.87, Fmax=8.84 / hour, fuel=pl.Resources.natural_gas, taxation=taxation))

        parts.add(pl.Boiler(name='Existing Boiler C', eta=0.89, Fmax=8.84 / hour, fuel=pl.Resources.natural_gas, taxation=taxation))
        
        parts.add(pl.Boiler(name='Existing Boiler D', eta= 0.77, Fmax= 8.84 / hour, fuel=pl.Resources.natural_gas, taxation=taxation))


        print('!! -- TRUE CAPACITY IS 45 MW - RUNNING AT 25 MW -- !!')
        # Running waste incinerator at 25 MW output max according to D4.2 p 32, techincal limit is 45
        parts.add(
            pl.LinearCHP(name='Existing Waste Incinerator', fuel=pl.Resources.waste, alpha=0.46, eta=0.81, Fmax= 25/hour, taxation=taxation)
            )  
        
        parts.add(
            pl.Accumulator(name='Existing Accumulator', resource=pl.Resources.heat, max_flow=60/hour, max_energy= 220, loss_factor = 0.005, t_start = parameters['t_start'], t_end = parameters['t_end'])
            )

        """ Production alternatives for the scenarios"""
        
        solar_data=self.get_solar_data(parameters['time_unit'])
        print("""!! -- Dividing investment cost LinearCHP by max_capacity so cost is EUR/MW-- !!""")
        parts.add(
            pl.LinearCHP(
                name = input_data['CHP']['name'],
                eta = input_data['CHP']['eta'],
                alpha = input_data['CHP']['alpha'],
                Fmax = input_data['CHP']['capacity'] /hour,
                fuel =  input_data['CHP']['resource'],
                taxation = input_data['CHP']['taxation'],  #ska vara taxation här men fick inte rätt då
                investment_cost = self.annuity(parameters['interest_rate'], input_data['CHP']['lifespan'], input_data['CHP']['investment_cost']) / (input_data['CHP']['max_capacity'] if input_data['CHP']['max_capacity'] else 1),
                max_capacity =  input_data['CHP']['max_capacity']
                )
        )
        
        if '2050' in year:
            if 'Trade_off' in scenario:
                parts.add(
                    pl.LinearCHP(
                    name = input_data['CHP invest']['name'],
                    eta = input_data['CHP invest']['eta'],
                    alpha = input_data['CHP invest']['alpha'],
                    Fmax = input_data['CHP invest']['capacity'] /hour,
                    max_capacity = input_data['CHP invest']['max_capacity']/hour,
                    fuel =  input_data['CHP invest']['resource'],
                    taxation = input_data['CHP invest']['taxation'],  #ska vara taxation här men fick inte rätt då
                    investment_cost = self.annuity(parameters['interest_rate'], input_data['CHP invest']['lifespan'], input_data['CHP invest']['investment_cost'])))
        
        parts.add(
            pl.SolarPV(
                name = input_data['SolarPV']['name'],
                G = solar_data['Mean Irradiance [W/m2]'],
                T = solar_data['Mean temperature [C]'], 
                max_capacity = None if input_data['SolarPV']['max_capacity'] is None else float(input_data['SolarPV']['max_capacity']),
                capacity = input_data['SolarPV']['capacity']/hour, #Eller capacity borde väl inte anges för investment option
                taxation = input_data['SolarPV']['taxation'], 
                investment_cost = self.annuity(parameters['interest_rate'], input_data['SolarPV']['lifespan'], input_data['SolarPV']['investment_cost'])))
        
        if '2050' in year:
            parts.add(
                pl.Accumulator(
                    name = input_data['Accumulator']['name'],
                    resource =  input_data['Accumulator']['resource'], 
                    max_flow = input_data['Accumulator']['max_flow']/hour, 
                    max_energy = input_data['Accumulator']['max_energy'], 
                    loss_factor = input_data['Accumulator']['loss_factor']/hour,
                    max_capacity = input_data['Accumulator']['max_capacity'],
                    investment_cost = self.annuity(parameters['interest_rate'], input_data['Accumulator']['lifespan'], input_data['Accumulator']['investment_cost']),
                    t_start = parameters['t_start'],
                    t_end = parameters['t_end']))  
        
        timeindependent_constraint = []
        if 'Trade_off_CO2' in scenario:
            timeindependent_constraint = [CO2_maximum] #, renovation_const, renovation_const_2]
        elif 'Trade_off' in scenario:
            timeindependent_constraint = [] # ,renovation_const, renovation_const_2] #!AK
        else:
            timeindependent_constraint = []
        
        return parts, timeindependent_constraint
Example #8
0
    def __init__(self,
                 start_steps=None,
                 fuel=None,
                 alpha=None,
                 eta=None,
                 capacity=None,
                 Fmin=None,
                 Fmax=None,
                 max_capacity=None,
                 taxation=None,
                 investment_cost=None,
                 **kwargs):
        super().__init__(**kwargs)

        mode_names = ('off', 'starting', 'on')
        with fs.namespace(self):
            modes = OrderedDict(
                (n, fs.VariableCollection(name=n, domain=fs.Domain.binary))
                for n in mode_names)
            F_on = fs.VariableCollection(lb=0, name='F_on')  # Fuel use if on
            inv = fs.Variable(domain=fs.Domain.binary)

        self.test = {
            'start_steps': start_steps,
            'fuel': fuel,
            'alpha': alpha,
            'eta': eta,
            'capacity': capacity,
            'Fmin': Fmin,
            'Fmax': Fmax,
            'max_capacity': max_capacity,
            'taxation': taxation,
            'investment_cost': investment_cost
        }
        self.inv = inv
        self.modes = modes

        if max_capacity:
            self.max_capacity = max_capacity
            Fmin = 0.2 * max_capacity * (1 + alpha) / eta
            Fmax = max_capacity * (1 + alpha) / eta
            self.investment_cost = inv * investment_cost
            self.constraints += self.max_production
            self.static_variables = {inv}
        elif capacity:
            Fmin = 0.2 * capacity * (1 + alpha) / eta
            Fmax = capacity * (1 + alpha) / eta
            self.static_variables = {}
            self.investment_cost = investment_cost
        else:
            self.static_variables = {}
            self.investment_cost = investment_cost

        self.consumption[fuel] = lambda t: F_on(t) + modes['starting'](t
                                                                       ) * Fmin
        self.production[Resources.heat] = lambda t: F_on(t) * eta / (alpha + 1)
        self.production[Resources.power] = lambda t: alpha * self.production[
            Resources.heat](t)

        self.cost = lambda t: self.consumption[fuel](
            t) * 0  #_CHP_cost_func(self, taxation, fuel)

        on_or_starting = lambda t: modes['on'](t) + modes['starting'](t)

        def mode_constraints(t):
            """ Yields mode constraints, if 'start_steps' is provided as 'n' the unit will have 
            to be 'starting' for 'n' time indices and can be turned to 'on' in the n+1 time index
            """
            yield Constraint(fs.Eq(fs.Sum(m(t) for m in modes.values()), 1),
                             desc='Exactly one mode at a time')

            if start_steps:
                recent_sum = fs.Sum(
                    on_or_starting(tau)
                    for tau in self.iter_times(t, -(start_steps), 0))
                yield Constraint(
                    modes['on'](t) <= recent_sum / (start_steps),
                    desc=
                    "'on' mode is only allowed after start_steps in 'on' and 'starting'"
                )

            yield Constraint(
                self.consumption[fuel](t) <=
                Fmax * modes['on'](t) + Fmin * modes['starting'](t),
                desc='Max fuel use when on or starting')

            yield Constraint(
                self.consumption[fuel](t) >= Fmin * modes['on'](t),
                desc='Min fuel use when on')

        self.constraints += mode_constraints
        self.state_variables = lambda t: {F_on(
            t)} | {var(t)
                   for var in modes.values()}
Example #9
0
def non_callable_constraint():
    cl = Cluster(resource=RESOURCE)
    cl.constraints += fs.Variable() == 3