Groups keyboard shortcuts have been updated
Dismiss
See shortcuts

two-indexed variable in Pyomo, using for declaring the variable in time and section/block

63 views
Skip to first unread message

Armaghan Bhr

unread,
Aug 2, 2020, 4:34:50 AM8/2/20
to Pyomo Forum
Hi there!

I'm trying to model a heat exchanger with n segments in pyomo but I get weird results. if I just use the time-dependant variable (without any segment index for the variable), the correct result comes out. However, when considering segments as another index for the T variable, I face the issue(unrealistic fluctuations).

n_segments = self.params['n_segments'].v()  # self.n_heat_exchanger
n_hex = range(1, n_segments + 1) #self.
self.n_hex = Set(initialize=n_hex)
self.TIME = Set(initialize=range(n_steps))

heat_profile
= self.params['heat_profile']
def _heat_flow(b, t, c=None):
   
return b.mult * heat_profile.v(t, c)
lines = self.params['lines'].v()               # done in fixedprofile
    self.block.temperatures = Var(lines, self.TIME) # for primary side               # done in fixedprofile
    self.block.temperature_hex_in = Var(self.TIME,self.n_hex) # clod/hot temperature along the h.ex # add in and out   #lines_ch
    self.block.temperature_hex_out = Var(self.TIME, self.n_hex)  # clod/hot temperature along the h.ex                  #lines_ch

    def _mass_flow(b, t, c=None):
       
return abs(self.params['mass_flow'].v(t, c))

   
if self.repr_days is None:
       
self.block.mass_flow = Param(self.TIME,
                                     
rule=_mass_flow,
                                     
mutable=not self.temperature_driven)
       
self.block.heat_flow = Param(self.TIME, rule=_heat_flow,
                                     
mutable=not self.temperature_driven)
   
else:
       
self.block.mass_flow = Param(self.TIME, self.REPR_DAYS,
                                     
rule=_mass_flow,
                                     
mutable=not self.temperature_driven)
       
self.block.heat_flow = Param(self.TIME, self.REPR_DAYS,
                                     
rule=_heat_flow,
                                     
mutable=not self.temperature_driven)

    ############# done in fixedprofile
    def _init_temperatures(b, l):
       
return b.temperatures[l, 0] == self.params['temperature_' + l].v()

   
self.block.init_temperatures = Constraint(lines, rule=_init_temperatures)
   
#############

    #               boundary conditions for in / out temperatures of the first and last blocks
    def _decl_temperatures_in(b, t):
       
return b.temperature_hex_in[t, 1] == b.temperatures['supply', t]

   
self.block.decl_temperature_in = Constraint(self.TIME,
                                             
rule=_decl_temperatures_in)

   
def _decl_temperatures_out(b, t):
       
return b.temperature_hex_out[t, n_segments] == b.temperatures['return', t]

   
self.block.decl_temperature_out = Constraint(self.TIME,
                                             
rule=_decl_temperatures_out)

    #############
    #                       temperature relationship between different blocks
    def _temp_blocks(b, t, n): #ch,
        if not n == n_segments:
           
return b.temperature_hex_out[t, n] == b.temperature_hex_in[t, n + 1]
        else:
           
return Constraint.Skip

   
self.block.temp_blocks = Constraint(self.TIME, self.n_hex, rule=_temp_blocks) #lines_ch,

    # check to change, for loop doesn't work here! :(f

    def _decl_temperatures(b, t, n):
       
if t==0:
           
return Constraint.Skip
       
elif b.mass_flow[t] == 0:
           
return Constraint.Skip
       
else: # it's about the water temperatures coming from/to the primary thermal grid
            return b.temperature_hex_in[t, n] - b.temperature_hex_out[t, n] == b.heat_flow[t]/n_segments/b.mass_flow[t] / self.cp

    self.block.decl_temperatures = Constraint(self.TIME, self.n_hex, rule=_decl_temperatures)

    ############# min supply temperature/ lower bound ###################
    uslack = self.make_slack('temperature_max_uslack', self.TIME)
    lslack
= self.make_slack('temperature_max_l_slack', self.TIME)

    ub
= self.params['temperature_max'].v()
    lb
= self.params['temperature_min'].v()

   
def _max_temp(b, t):
       
return self.constrain_value(b.temperatures['supply', t],
                                    ub
,
                                   
ub=True,
                                   
slack_variable=uslack[t])

   
def _min_temp(b, t):
       
return self.constrain_value(b.temperatures['supply', t],
                                    lb
,
                                   
ub=False,
                                   
slack_variable=lslack[t])

   
self.block.max_temp = Constraint(self.TIME, rule=_max_temp)
   
self.block.min_temp = Constraint(self.TIME, rule=_min_temp)

    lslack
= self.make_slack('temperature_l_slack', self.TIME)

    lb
= self.params['temperature_min'].v()

else:
   
raise Exception('It is not temperature driven!')

self.logger.info('Optimization model {} {} compiled'.
                 format
(self.__class__, self.name))

self.compiled = True


for n_segments=1 in this code, I expect to get the same result as when the variable is just time dependant (with no n_segments index). So, is there any problem with the indexing I use?

Reply all
Reply to author
Forward
0 new messages