def convert_prob(self): self.logger.info("Converting optimization problem") self.model.con_list = ConstraintList() # Set of objective functions self.model.Os = Set(ordered=True, initialize=[o + 2 for o in self.iter_obj2]) # Slack for objectives introduced as constraints self.model.Slack = Var(self.model.Os, within=NonNegativeReals) self.model.e = Param( self.model.Os, initialize=[np.nan for _ in self.model.Os], within=Any, mutable=True, ) # RHS of constraints # Add p-1 objective functions as constraints for o in range(1, self.n_obj): self.model.obj_list[1].expr += self.opts.eps * ( 10 ** (-1 * (o - 1)) * self.model.Slack[o + 1] / self.obj_range[o - 1] ) self.model.con_list.add( expr=self.model.obj_list[o + 1].expr - self.model.Slack[o + 1] == self.model.e[o + 1] )
def _apply_to(self, instance, **kwds): options = kwds.pop('options', {}) bound = kwds.pop('mpec_bound', 0.0) # # Create a mutable parameter that defines the value of the upper bound # on the constraints # bound = options.get('mpec_bound', bound) instance.mpec_bound = Param(mutable=True, initialize=bound) # # Setup transformation data # tdata = instance._transformation_data['mpec.simple_nonlinear'] tdata.compl_cuids = [] # # Iterate over the model finding Complementarity components # for complementarity in instance.component_objects( Complementarity, active=True, descend_into=(Block, Disjunct), sort=SortComponents.deterministic): block = complementarity.parent_block() for index in sorted(complementarity.keys()): _data = complementarity[index] if not _data.active: continue _data.to_standard_form() # _type = getattr(_data.c, "_complementarity_type", 0) if _type == 1: # # Constraint expression is bounded below, so we can replace # constraint c with a constraint that ensures that either # constraint c is active or variable v is at its lower bound. # _data.ccon = Constraint( expr=(_data.c.body - _data.c.lower) * _data.v <= instance.mpec_bound) del _data.c._complementarity_type elif _type == 3: # # Variable v is bounded above and below. We can define # _data.ccon_l = Constraint( expr=(_data.v - _data.v.bounds[0]) * _data.c.body <= instance.mpec_bound) _data.ccon_u = Constraint( expr=(_data.v - _data.v.bounds[1]) * _data.c.body <= instance.mpec_bound) del _data.c._complementarity_type elif _type == 2: #pragma:nocover raise ValueError( "to_standard_form does not generate _type 2 expressions" ) tdata.compl_cuids.append(ComponentUID(complementarity)) block.reclassify_component_type(complementarity, Block)
def beforeChild(self, node, child, child_idx): if type(child) is IndexTemplate: return False, child if type(child) is EXPR.GetItemExpression: _id = _GetItemIndexer(child) if _id not in self.templatemap: self.templatemap[_id] = Param(mutable=True) self.templatemap[_id].construct() self.templatemap[_id]._name = "%s[%s]" % ( _id.base.name, ','.join(str(x) for x in _id.args)) return False, self.templatemap[_id] return super().beforeChild(node, child, child_idx)
def visiting_potential_leaf(self, node): if type(node) is IndexTemplate: return True, node if type(node) is EXPR.GetItemExpression: _id = _GetItemIndexer(node) if _id not in self.templatemap: self.templatemap[_id] = Param(mutable=True) self.templatemap[_id].construct() self.templatemap[_id]._name = "%s[%s]" % ( _id.base.name, ','.join(str(x) for x in _id.args)) return True, self.templatemap[_id] return super(Pyomo2Scipy_Visitor, self).visiting_potential_leaf(node)
def visiting_potential_leaf(self, node): if type(node) in native_numeric_types or \ not node.is_expression_type() or\ type(node) is IndexTemplate: return True, node if type(node) is EXPR.GetItemExpression: _id = _GetItemIndexer(node) if _id not in self.templatemap: self.templatemap[_id] = Param(mutable=True) self.templatemap[_id].construct() _args = [] self.templatemap[_id]._name = "%s[%s]" % ( node._base.name, ','.join(str(x) for x in _id._args)) return True, self.templatemap[_id] return False, None
def make_noisy(self, cov_dict, conf_level=2): self.d1.name = "Noisy plant (d1)" k = 0 for x in self.states: s = getattr(self.d1, x) #: state xicc = getattr(self.d1, x + "_icc") xicc.deactivate() for j in self.state_vars[x]: self.xp_l.append(s[(1, 0) + j]) self.xp_key[(x, j)] = k k += 1 self.d1.xS_pnoisy = Set(initialize=[ i for i in range(0, len(self.xp_l)) ]) #: Create set of noisy_states self.d1.w_pnoisy = Var(self.d1.xS_pnoisy, initialize=0.0) #: Model disturbance self.d1.Q_pnoisy = Param(self.d1.xS_pnoisy, initialize=1, mutable=True) self.d1.obj_fun_noisy = Objective( sense=maximize, expr=0.5 * sum(self.d1.Q_pnoisy[k] * self.d1.w_pnoisy[k]**2 for k in self.d1.xS_pnoisy)) self.d1.ics_noisy = ConstraintList() k = 0 for x in self.states: s = getattr(self.d1, x) #: state xic = getattr(self.d1, x + "_ic") for j in self.state_vars[x]: expr = s[(1, 1) + j] == xic[j] + self.d1.w_pnoisy[k] self.d1.ics_noisy.add(expr) k += 1 for key in cov_dict: vni = key v_i = self.xp_key[vni] self.d1.Q_pnoisy[v_i].value = cov_dict[vni] self.d1.w_pnoisy[v_i].setlb(-conf_level * cov_dict[vni]) self.d1.w_pnoisy[v_i].setub(conf_level * cov_dict[vni]) with open("debug.txt", "w") as f: self.d1.Q_pnoisy.display(ostream=f) self.d1.obj_fun_noisy.pprint(ostream=f) self.d1.ics_noisy.pprint(ostream=f) self.d1.w_pnoisy.display(ostream=f)
def set_testl(market_instances_list, airport_list, market_data, segment_travel_time, time_zone_dict, iti_dict, fleet_data, passeger_type_dict, attr_value, marketpt_attr_sum, solver): """ 很多输入变量都是字典,就是为了在模型中生成子集的时候有筛选功能 即 if dict【m】 in dict :param airport_list: :param market_data: :param segment_travel_time: :param iti_dict:itinerary number key ,info value :{0: {'market': "M('SEA', 'LAX')", 'non_stop': ('SEA', 'LAX'), ('SEA', 'LAX'): 1, 'legs': [('SEA', 'LAX')]} :param fleet_data: :param passeger_type_dict: passenger_type as key , and it's proportions :param attr_value: :param marketpt_attr_sum: :param solver: :return: time_table, q_variable for each itinerary, """ market_iti = {} #market:itinerary list for m in market_instances_list: l = [ i for i, v in iti_dict.items() if v['market'] == 'M' + str(m.od_pair) ] market_iti.update({m: l}) model = ConcreteModel() market = list(market_data.keys()) #['M' + str(m.od_pair) for m in ] # market_segment={m:[(market_data[m][4],market_data[m][5])] for m in market_data.keys()} model.M = Set(initialize=market, doc='Player Market_obj') model.Mi = Set(list(market_iti.keys()), initialize=market_iti, doc='Player Market_obj') model.AP = Set(initialize=airport_list) model.Segment = Set(initialize=((i, j) for i in model.AP for j in model.AP if i != j)) # create time spot [1-72] and it's time a = np.linspace(1, int((1440 - 360) / 15), int((1440 - 360) / 15)) time_list = np.arange(360, 1440, 15) time_dict = dict(zip(a, time_list)) # reverse_time_dict = {v: k for k, v in time_dict.items()} model.T = Set( initialize=a, ordered=True, doc='Time period from 300 min to 1440 ,step :15min,number:73') model.I = Set(initialize=iti_dict.keys(), doc='itinerary _index,size 4334') model.Im = Set(initialize=((m, i) for m in model.M for i in market_iti[m]), doc='tuple(m,i),size 4334') # 筛选出只在m的itinerary 的 号码 model.PT = Set(initialize=passeger_type_dict.keys()) model.F = Set(initialize=fleet_data.keys()) d = {} #create a dict as which OD and time get all itinerary_index in it for ap1, ap2 in model.Segment: for t in model.T: v = [] for i, va in iti_dict.items(): if (ap1, ap2) in va['legs'] and t == va[(ap1, ap2)]: v.append(i) d[(ap1, ap2, t)] = v model.St = Set( list(d.keys()), initialize=d) # index as (ap1,ap2,time) get [itinerary index list] def _filter3(model, i, m, ap1, ap2, t): return i in model.Mi[m].value and i in model.St[(ap1, ap2, t)].value # def Parameters demand_pt = { } # get demand of pt in the market by total demand times its proportion print("passenger_type_proportion:", passeger_type_dict) for m, va in market_data.items(): for ty, rato in passeger_type_dict.items(): demand_pt.update({(m, ty): va[0] * rato}) # market demand times proportions model.Dem = Param(model.M, model.PT, initialize=demand_pt, doc='Market demand for each type of passenger') price_dict = {} for i in model.I: rato = np.linspace(1.3, 0.7, len(passeger_type_dict)) for index, ty in enumerate(passeger_type_dict): if iti_dict[i]['non_stop']: price_dict.update({ (i, ty): market_data[iti_dict[i]['market']][2] * rato[index] }) # market_data[m][2] is price else: price_dict.update({ (i, ty): 0.8 * market_data[iti_dict[i]['market']][2] * rato[index] }) # market_data[m][2] is price model.p = Param(model.I, model.PT, initialize=price_dict) model.Avail = Param( model.F, initialize={fleet: value[0] for fleet, value in fleet_data.items()}) model.Cap = Param( model.F, initialize={fleet: value[1] for fleet, value in fleet_data.items()}) model.distance = Param(model.Segment, initialize={(value[-2], value[-1]): value[1] for value in market_data.values()}) def ope_cost(model, ap1, ap2, f): if model.distance[ap1, ap2] <= 3106: return (1.6 * model.distance[ap1, ap2] + 722) * (model.Cap[f] + 104) * 0.019 else: return (1.6 * model.distance[ap1, ap2] + 2200) * (model.Cap[f] + 211) * 0.0115 model.Ope = Param(model.Segment, model.F, initialize=ope_cost, doc='cost') freq = {(market_data[m][4], market_data[m][5]): market_data[m][3] for m in market_data.keys()} model.Freq = Param(model.Segment, initialize=freq) model.A = Param(model.I, model.PT, initialize=attr_value) model.Am = Param(model.M, model.PT, initialize=marketpt_attr_sum) # Step 2: Define decision variables model.x = Var(model.Segment, model.F, model.T, within=Binary) model.y_1 = Var(model.F, model.AP, model.T, within=PositiveIntegers) model.y_2 = Var(model.F, model.AP, model.T, within=PositiveIntegers) model.q = Var(model.I, model.PT, within=NonNegativeReals) model.non_q = Var(model.M, model.PT, within=NonNegativeReals ) # number of pax that choose others airine and no fly. # Step 3: Define Objective def obj_rule(model): return sum(model.q[i, pt] * model.p[i, pt] for i in model.I for pt in model.PT) - sum(model.Ope[s, f] * model.x[s, f, t] for s in model.Segment for f in model.F for t in model.T) model.obj = Objective(rule=obj_rule, sense=maximize) def obj_cost(model): return sum(model.Ope[s, f] * model.x[s, f, t] for s in model.Segment for f in model.F for t in model.T) model.obj_cost = Expression(rule=obj_cost) def obj_revenue(model): return sum(model.q[i, pt] * model.p[i, pt] for i in model.I for pt in model.PT) model.obj_revenue = Expression(rule=obj_revenue) # add constraint # Aircraft count: def aircraft_con(model, f): return sum(model.y_1[f, ap, model.T[1]] for ap in model.AP) <= model.Avail[f] model.count = Constraint(model.F, rule=aircraft_con) # flow balance cons def flow_balance_1(model, f, ap): return model.y_1[f, ap, model.T[1]] == model.y_2[f, ap, model.T[-1]] model.con_fb_1 = Constraint(model.F, model.AP, rule=flow_balance_1) def flow_balance_2(model, f, ap, t): # if t == model.T[-1]: # return Constraint.Skip # else: return model.y_1[f, ap, t + 1] == model.y_2[f, ap, t] def filter2(model, t): return t != model.T[-1] model.Tm = Set(initialize=(i for i in model.T if i != model.T[-1])) #model.con_fb_2 = Constraint(model.F, model.AP, model.T, rule=flow_balance_2) model.con_fb_2 = Constraint(model.F, model.AP, model.Tm, rule=flow_balance_2) # time_zone_dict={('ANC', 'PDX'): 60, ('SEA', 'PDX'): 0, ('SEA', 'ANC'): -60, ('ANC', 'LAX'): 60, ('PDX', 'SEA'): 0, ('LAX', 'PDX'): 0, # ('LAX', 'SEA'): 0, ('PDX', 'ANC'): -60, ('SEA', 'LAX'): 0, ('ANC', 'SEA'): 60, ('LAX', 'ANC'): -60, ('PDX', 'LAX'): 0} Travel_time = segment_travel_time def flow_balance_3(model, f, ap, t): def D(s, t, turnaround=30): arrival_time = time_dict[t] dep_time = arrival_time - (Travel_time[s] + turnaround) - time_zone_dict[s] if dep_time >= 360: t0 = ((dep_time - 360) // 15) + 1 else: t0 = 72 - (abs(360 - dep_time) // 15) return t0 return model.y_1[f, ap, t] + sum( model.x[s, f, D(s, t)] for s in model.Segment if s[1] == ap) == model.y_2[f, ap, t] + sum( model.x[s, f, t] for s in model.Segment if s[0] == ap) model.con_fb_3 = Constraint(model.F, model.AP, model.T, rule=flow_balance_3) # Demand and capacity constrains: def attract_con(model, market, i, pt): return model.Am[market, pt] * ( model.q[i, pt] / model.Dem[market, pt]) <= model.A[i, pt] * ( model.non_q[market, pt] / model.Dem[market, pt]) model.attractiveness = Constraint(model.Im, model.PT, rule=attract_con) def capacity_con(model, ap1, ap2, t): return sum(model.q[i, pt] for i in d[(ap1, ap2, t)] for pt in model.PT) <= sum( model.Cap[f] * model.x[ap1, ap2, f, t] for f in model.F) model.con_d1 = Constraint(model.Segment, model.T, rule=capacity_con) def demand_market_con(model, market, pt): return sum(model.q[i, pt] for i in model.I if iti_dict[i]['market'] == market) + model.non_q[market, pt] == \ model.Dem[market, pt] model.con_d3 = Constraint(model.M, model.PT, rule=demand_market_con) # Itinerary selection constraints: model.AC = Set(initialize=model.I * model.M * model.Segment * model.T, filter=_filter3) def iti_selection(model, i, m, ap1, ap2, t, pt): # if i in market_iti[m] and i in d[(ap1, ap2, t)]: return sum(model.x[ap1, ap2, f, t] for f in model.F) >= model.q[i, pt] / model.Dem[m, pt] model.con_iti_selection = Constraint(model.AC, model.PT, rule=iti_selection) # Restrictions on fight leg variables: def flight_leg_con(model, ap1, ap2, t): return sum(model.x[ap1, ap2, f, t] for f in model.F) <= 1 model.con_leg_1 = Constraint(model.Segment, model.T, rule=flight_leg_con) def freq_con(model, ap1, ap2): return sum(model.x[ap1, ap2, f, t] for t in model.T for f in model.F) == model.Freq[ap1, ap2] model.con_let_2 = Constraint(model.Segment, rule=freq_con) print("____" * 5) # for con in model.component_map(Constraint).itervalues(): # con.pprint() SOLVER_NAME = solver TIME_LIMIT = 60 * 60 * 2 results = SolverFactory(SOLVER_NAME) if SOLVER_NAME == 'cplex': results.options['timelimit'] = TIME_LIMIT elif SOLVER_NAME == 'glpk': results.options['tmlim'] = TIME_LIMIT elif SOLVER_NAME == 'gurobi': results.options['TimeLimit'] = TIME_LIMIT com = results.solve(model, tee=True) com.write() #absgap = com.solution(0).gap # get x results in matrix form df_x = pd.DataFrame(columns=list(model.Segment), index=model.T) for s in model.Segment: for t in model.T: for f in model.F: if model.x[s, f, t].value > 0: df_x.loc[t, [s]] = f #df_x=df_x.reset_index()# return value is a dataframe of new time table # 所有的决策变量都遍历一遍 # for v in instance.component_objects(Var, active=True): # print("Variable", v) # varobject = getattr(instance, str(v)) # for index in varobject: # print(" ", index, varobject[index].value) varobject = getattr(model, 'q') q_data = {(i, pt): varobject[(i, pt)].value for (i, pt), v in varobject.items() if varobject[(i, pt)] != 0} df_q = pd.DataFrame.from_dict(q_data, orient="index", columns=["variable value"]) varobject2 = getattr(model, 'non_q') nonq_data = {(m, pt): varobject2[(m, pt)].value for (m, pt), v in varobject2.items() if varobject2[(m, pt)] != 0} # q = list(model.q.get_values().values()) # print('q = ', q) profit = model.obj() print('\nProfit = ', profit) cost = value_s(model.obj_cost()) #revenue=value_s(model.obj_revenue()) print('cost is:' * 10, cost) #print('revenue is:' * 10, revenue) ''' print('\nDecision Variables') #list_of_vars = [v.value for v in model.component_objects(ctype=Var, active=True, descend_into=True)] #var_names = [v.name for v in model.component_objects(ctype=Var, active=True, descend_into=True) if v.value!=0] # print("y=",y) model.obj.display() def pyomo_postprocess( options=None, instance=None, results=None ): model.x.display() pyomo_postprocess(None, model, results) for v in model.component_objects(Var, active=True): print("Variable component object", v) varobject = getattr(model, str(v)) for index in varobject: if varobject[index].value != 0: print(" ", index, varobject[index].value) ''' return df_x, q_data, profit, cost, nonq_data
""" CSTR from Rodrigo's thesis Returns: cstr_rodrigo_dae: The model itmod. Without discretization. """ #: if steady == True fallback to steady-state computation mod = ConcreteModel() #: mod.nfe_t = nfe_t #: #: mod.ncp_t = ncp_t mod.discretized = False ncstr = 1 mod.ncstr = Set(initialize=[i for i in range(0, ncstr)]) mod.t = ContinuousSet(bounds=(0, 1)) mod.Cainb = Param(default=1.0) mod.Tinb = Param(default=275.0) # mod.Tjinb = Param(default=250.0) #: Our control var mod.Tjinb = Var(mod.t, initialize=250) mod.u1 = Param(mod.t, default=250, mutable=True) #: We are making a sort-of port def u1_rule(m, i): return m.Tjinb[i] == m.u1[i] # mod.u1_cdummy = Constraint(mod.t, rule=lambda m, i: m.Tjinb[i] == mod.u1[i]) mod.u1_cdummy = Constraint(mod.t, rule=u1_rule)
def __init__(self, **kwargs): NmpcGen.__init__(self, **kwargs) self.int_file_mhe_suf = int(time.time())-1 # Need a list of relevant measurements y self.y = kwargs.pop('y', []) self.y_vars = kwargs.pop('y_vars', {}) # Need a list or relevant noisy-states z self.x_noisy = kwargs.pop('x_noisy', []) self.x_vars = kwargs.pop('x_vars', {}) self.deact_ics = kwargs.pop('del_ics', True) self.diag_Q_R = kwargs.pop('diag_QR', True) #: By default use diagonal matrices for Q and R matrices self.u = kwargs.pop('u', []) self.IgnoreProcessNoise = kwargs.pop('IgnoreProcessNoise', False) print("-" * 120) print("I[[create_lsmhe]] lsmhe (full) model created.") print("-" * 120) nstates = sum(len(self.x_vars[x]) for x in self.x_noisy) self.journalizer("I", self._c_it, "MHE with \t", str(nstates) + "states") self.journalizer("I", self._c_it, "MHE with \t", str(nstates*self.nfe_t*self.ncp_t) + "noise vars") self.lsmhe = self.d_mod(self.nfe_t, self.ncp_t, _t=self._t) self.lsmhe.name = "LSMHE (Least-Squares MHE)" self.lsmhe.create_bounds() #: create x_pi constraint #: Create list of noisy-states vars self.xkN_l = [] self.xkN_nexcl = [] self.xkN_key = {} k = 0 for x in self.x_noisy: n_s = getattr(self.lsmhe, x) #: Noisy-state for jth in self.x_vars[x]: #: the jth variable self.xkN_l.append(n_s[(1, 0) + jth]) self.xkN_nexcl.append(1) #: non-exclusion list for active bounds self.xkN_key[(x, jth)] = k k += 1 self.lsmhe.xkNk_mhe = Set(initialize=[i for i in range(0, len(self.xkN_l))]) #: Create set of noisy_states self.lsmhe.x_0_mhe = Param(self.lsmhe.xkNk_mhe, initialize=0.0, mutable=True) #: Prior-state self.lsmhe.wk_mhe = Param(self.lsmhe.fe_t, self.lsmhe.cp_ta, self.lsmhe.xkNk_mhe, initialize=0.0) \ if self.IgnoreProcessNoise else Expression(self.lsmhe.fe_t, self.lsmhe.cp_ta, self.lsmhe.xkNk_mhe) #: Model disturbance self.lsmhe.PikN_mhe = Param(self.lsmhe.xkNk_mhe, self.lsmhe.xkNk_mhe, initialize=lambda m, i, ii: 1. if i == ii else 0.0, mutable=True) #: Prior-Covariance self.lsmhe.Q_mhe = Param(range(1, self.nfe_t), self.lsmhe.xkNk_mhe, initialize=1, mutable=True) if self.diag_Q_R\ else Param(range(1, self.nfe_t), self.lsmhe.xkNk_mhe, self.lsmhe.xkNk_mhe, initialize=lambda m, t, i, ii: 1. if i == ii else 0.0, mutable=True) #: Disturbance-weight j = 0 for i in self.x_noisy: de_exp = getattr(self.lsmhe, "de_" + i) for k in self.x_vars[i]: for tfe in range(1, self.nfe_t+1): for tcp in range(1, self.ncp_t + 1): self.lsmhe.wk_mhe[tfe, tcp, j].set_value(de_exp[(tfe, tcp) + k]._body) de_exp[(tfe, tcp) + k].deactivate() j += 1 #: Create list of measurements vars self.yk_l = {} self.yk_key = {} k = 0 self.yk_l[1] = [] for y in self.y: m_v = getattr(self.lsmhe, y) #: Measured "state" for jth in self.y_vars[y]: #: the jth variable self.yk_l[1].append(m_v[(1, self.ncp_t) + jth]) self.yk_key[(y, jth)] = k #: The key needs to be created only once, that is why the loop was split k += 1 for t in range(2, self.nfe_t + 1): self.yk_l[t] = [] for y in self.y: m_v = getattr(self.lsmhe, y) #: Measured "state" for jth in self.y_vars[y]: #: the jth variable self.yk_l[t].append(m_v[(t, self.ncp_t) + jth]) self.lsmhe.ykk_mhe = Set(initialize=[i for i in range(0, len(self.yk_l[1]))]) #: Create set of measured_vars self.lsmhe.nuk_mhe = Var(self.lsmhe.fe_t, self.lsmhe.ykk_mhe, initialize=0.0) #: Measurement noise self.lsmhe.yk0_mhe = Param(self.lsmhe.fe_t, self.lsmhe.ykk_mhe, initialize=1.0, mutable=True) self.lsmhe.hyk_c_mhe = Constraint(self.lsmhe.fe_t, self.lsmhe.ykk_mhe, rule= lambda mod, t, i:mod.yk0_mhe[t, i] - self.yk_l[t][i] - mod.nuk_mhe[t, i] == 0.0) self.lsmhe.hyk_c_mhe.deactivate() self.lsmhe.R_mhe = Param(self.lsmhe.fe_t, self.lsmhe.ykk_mhe, initialize=1.0, mutable=True) if self.diag_Q_R else \ Param(self.lsmhe.fe_t, self.lsmhe.ykk_mhe, self.lsmhe.ykk_mhe, initialize=lambda mod, t, i, ii: 1.0 if i == ii else 0.0, mutable=True) f = open("file_cv.txt", "w") f.close() #: Constraints for the input noise for u in self.u: # cv = getattr(self.lsmhe, u) #: Get the param # c_val = [value(cv[i]) for i in cv.keys()] #: Current value # self.lsmhe.del_component(cv) #: Delete the param # self.lsmhe.add_component(u + "_mhe", Var(self.lsmhe.fe_t, initialize=lambda m, i: c_val[i-1])) self.lsmhe.add_component("w_" + u + "_mhe", Var(self.lsmhe.fe_t, initialize=0.0)) #: Noise for input self.lsmhe.add_component("w_" + u + "c_mhe", Constraint(self.lsmhe.fe_t)) self.lsmhe.equalize_u(direction="r_to_u") # cc = getattr(self.lsmhe, u + "_c") #: Get the constraint for input con_w = getattr(self.lsmhe, "w_" + u + "c_mhe") #: Get the constraint-noisy var_w = getattr(self.lsmhe, "w_" + u + "_mhe") #: Get the constraint-noisy ce = getattr(self.lsmhe, u + "_e") #: Get the expression cp = getattr(self.lsmhe, u) #: Get the param con_w.rule = lambda m, i: cp[i] == ce[i] + var_w[i] con_w.reconstruct() con_w.deactivate() # con_w.rule = lambda m, i: cp[i] == cv[i] + var_w[i] # con_w.reconstruct() # with open("file_cv.txt", "a") as f: # cc.pprint(ostream=f) # con_w.pprint(ostream=f) # f.close() self.lsmhe.U_mhe = Param(range(1, self.nfe_t + 1), self.u, initialize=1, mutable=True) #: Deactivate icc constraints if self.deact_ics: pass # for i in self.states: # self.lsmhe.del_component(i + "_icc") #: Maybe only for a subset of the states else: for i in self.states: if i in self.x_noisy: ic_con = getattr(self.lsmhe, i + "_icc") for k in self.x_vars[i]: ic_con[k].deactivate() #: Put the noise in the continuation equations (finite-element) j = 0 self.lsmhe.noisy_cont = ConstraintList() for i in self.x_noisy: # cp_con = getattr(self.lsmhe, "cp_" + i) cp_exp = getattr(self.lsmhe, "noisy_" + i) # self.lsmhe.del_component(cp_con) for k in self.x_vars[i]: #: This should keep the same order for t in range(1, self.nfe_t): self.lsmhe.noisy_cont.add(cp_exp[t, k] == 0.0) # self.lsmhe.noisy_cont.add(cp_exp[t, k] == 0.0) j += 1 # cp_con.reconstruct() j = 0 self.lsmhe.noisy_cont.deactivate() #: Expressions for the objective function (least-squares) self.lsmhe.Q_e_mhe = 0.0 if self.IgnoreProcessNoise else Expression( expr=0.5 * sum( sum( sum(self.lsmhe.Q_mhe[1, k] * self.lsmhe.wk_mhe[i, j, k]**2 for k in self.lsmhe.xkNk_mhe) for j in range(1, self.ncp_t +1)) for i in range(1, self.nfe_t+1))) if self.diag_Q_R else Expression( expr=sum(sum(self.lsmhe.wk_mhe[i, j] * sum(self.lsmhe.Q_mhe[i, j, k] * self.lsmhe.wk_mhe[i, 1, k] for k in self.lsmhe.xkNk_mhe) for j in self.lsmhe.xkNk_mhe) for i in range(1, self.nfe_t))) self.lsmhe.R_e_mhe = Expression( expr=0.5 * sum( sum( self.lsmhe.R_mhe[i, k] * self.lsmhe.nuk_mhe[i, k]**2 for k in self.lsmhe.ykk_mhe) for i in self.lsmhe.fe_t)) if self.diag_Q_R else Expression( expr=sum(sum(self.lsmhe.nuk_mhe[i, j] * sum(self.lsmhe.R_mhe[i, j, k] * self.lsmhe.nuk_mhe[i, k] for k in self.lsmhe.ykk_mhe) for j in self.lsmhe.ykk_mhe) for i in self.lsmhe.fe_t)) expr_u_obf = 0 for i in self.lsmhe.fe_t: for u in self.u: var_w = getattr(self.lsmhe, "w_" + u + "_mhe") #: Get the constraint-noisy expr_u_obf += self.lsmhe.U_mhe[i, u] * var_w[i] ** 2 self.lsmhe.U_e_mhe = Expression(expr=0.5 * expr_u_obf) # how about this # with open("file_cv.txt", "a") as f: # self.lsmhe.U_e_mhe.pprint(ostream=f) # f.close() self.lsmhe.Arrival_e_mhe = Expression( expr=0.5 * sum((self.xkN_l[j] - self.lsmhe.x_0_mhe[j]) * sum(self.lsmhe.PikN_mhe[j, k] * (self.xkN_l[k] - self.lsmhe.x_0_mhe[k]) for k in self.lsmhe.xkNk_mhe) for j in self.lsmhe.xkNk_mhe)) self.lsmhe.Arrival_dummy_e_mhe = Expression( expr=100000.0 * sum((self.xkN_l[j] - self.lsmhe.x_0_mhe[j]) ** 2 for j in self.lsmhe.xkNk_mhe)) self.lsmhe.obfun_dum_mhe_deb = Objective(sense=minimize, expr=self.lsmhe.Q_e_mhe) self.lsmhe.obfun_dum_mhe = Objective(sense=minimize, expr=self.lsmhe.R_e_mhe + self.lsmhe.Q_e_mhe + self.lsmhe.U_e_mhe) # no arrival self.lsmhe.obfun_dum_mhe.deactivate() self.lsmhe.obfun_mhe_first = Objective(sense=minimize, expr=self.lsmhe.Arrival_dummy_e_mhe + self.lsmhe.Q_e_mhe) self.lsmhe.obfun_mhe_first.deactivate() self.lsmhe.obfun_mhe = Objective(sense=minimize, expr=self.lsmhe.Arrival_dummy_e_mhe + self.lsmhe.R_e_mhe + self.lsmhe.Q_e_mhe + self.lsmhe.U_e_mhe) self.lsmhe.obfun_mhe.deactivate() # with open("file_cv.txt", "a") as f: # self.lsmhe.obfun_mhe.pprint(ostream=f) # f.close() self._PI = {} #: Container of the KKT matrix self.xreal_W = {} self.curr_m_noise = {} #: Current measurement noise self.curr_y_offset = {} #: Current offset of measurement for y in self.y: for j in self.y_vars[y]: self.curr_m_noise[(y, j)] = 0.0 self.curr_y_offset[(y, j)] = 0.0 self.s_estimate = {} self.s_real = {} for x in self.x_noisy: self.s_estimate[x] = [] self.s_real[x] = [] self.y_estimate = {} self.y_real = {} self.y_noise_jrnl = {} self.yk0_jrnl = {} for y in self.y: self.y_estimate[y] = [] self.y_real[y] = [] self.y_noise_jrnl[y] = [] self.yk0_jrnl[y] = []
def compile(self, model, start_time): """ Build the structure of the optimization model :param model: The entire optimization model :param start_time: The optimization start time :return: """ Component.compile(self, model, start_time) self.dn = self.params['diameter'].v() if self.dn is not 0: self.mflo_max = self.mflo_max_list[self.dn] Rs = self.Rs[self.dn] self.f = self.f_mult * self.f_list[self.dn] else: self.mflo_max = 0 self.f = 0 Te = self.params["Te"] self.temp_sup = self.params['temperature_supply'].v() self.temp_ret = self.params['temperature_return'].v() if self.compiled: self.block.mass_flow_max = self.mflo_max self.logger.debug('Redefining mass_flow_max') self.construct_pumping_constraints() if self.repr_days is None: for t in self.TIME: if self.dn is not 0: self.block.heat_loss_nom[t] = ( self.temp_sup + self.temp_ret - 2 * Te.v(t)) / Rs else: self.block.heat_loss_nom[t] = 0 else: for t in self.TIME: for c in self.REPR_DAYS: if self.dn is not 0: self.block.heat_loss_nom[t, c] = (self.temp_sup + self.temp_ret - 2 * Te.v(t, c)) / Rs else: self.block.heat_loss_nom[t, c] = 0 else: """ Parameters and sets """ self.block.mass_flow_max = Param(initialize=self.mflo_max, mutable=True) # Maximal heat loss per unit length def _heat_loss(b, t, c=None): """ Rule to calculate maximal heat loss per unit length :param b: block identifier :param t: time index :param dn: DN index :return: Heat loss in W/m """ if self.dn is not 0: dq = (self.temp_sup + self.temp_ret - 2 * Te.v(t, c)) / Rs else: dq = 0 return dq if self.repr_days is None: self.block.heat_loss_nom = Param(self.TIME, rule=_heat_loss, mutable=True) else: self.block.heat_loss_nom = Param(self.TIME, self.REPR_DAYS, rule=_heat_loss, mutable=True) """ Variables """ mflo_ub = ( -self.block.mass_flow_max, self.block.mass_flow_max) if self.allow_flow_reversal else ( 0, self.block.mass_flow_max) # Real valued if self.repr_days is None: self.block.heat_flow_in = Var(self.TIME, doc='Heat flow entering in-node') self.block.heat_flow_out = Var( self.TIME, doc='Heat flow exiting out-node') self.block.mass_flow = Var( self.TIME, bounds=mflo_ub, doc='Mass flow rate entering in-node and exiting out-node') self.block.heat_loss_tot = Var(self.TIME, within=NonNegativeReals, doc='Total heat lost from pipe') self.block.mass_flow_abs = Var( self.TIME, within=NonNegativeReals, doc='Absolute value of mass flow rate') else: self.block.heat_flow_in = Var(self.TIME, self.REPR_DAYS, doc='Heat flow entering in-node') self.block.heat_flow_out = Var( self.TIME, self.REPR_DAYS, doc='Heat flow exiting out-node') self.block.mass_flow = Var( self.TIME, self.REPR_DAYS, bounds=mflo_ub, doc='Mass flow rate entering in-node and exiting out-node') self.block.heat_loss_tot = Var(self.TIME, self.REPR_DAYS, within=NonNegativeReals, doc='Total heat lost from pipe') self.block.mass_flow_abs = Var( self.TIME, self.REPR_DAYS, within=NonNegativeReals, doc='Absolute value of mass flow rate') """ Pipe model """ ############## # EQUALITIES # ############## def _eq_heat_flow_bal(b, t, c=None): if self.repr_days is None: return b.heat_flow_in[t] == b.heat_loss_tot[t] + \ b.heat_flow_out[t] else: return b.heat_flow_in[t, c] == b.heat_loss_tot[t, c] + \ b.heat_flow_out[t, c] if self.repr_days is None: self.block.eq_heat_flow_bal = Constraint( self.TIME, rule=_eq_heat_flow_bal) else: self.block.eq_heat_flow_bal = Constraint( self.TIME, self.REPR_DAYS, rule=_eq_heat_flow_bal) ################ # INEQUALITIES # ################ def _mass_flow_pos(b, t, c=None): if self.repr_days is None: return b.mass_flow_abs[t] >= b.mass_flow[t] else: return b.mass_flow_abs[t, c] >= b.mass_flow[t, c] def _mass_flow_neg(b, t, c=None): if self.repr_days is None: return b.mass_flow_abs[t] >= -b.mass_flow[t] else: return b.mass_flow_abs[t, c] >= -b.mass_flow[t, c] if self.repr_days is None: self.block.ineq_mass_flow_pos = Constraint(self.TIME, rule=_mass_flow_pos) self.block.ineq_mass_flow_neg = Constraint(self.TIME, rule=_mass_flow_neg) else: self.block.ineq_mass_flow_pos = Constraint(self.TIME, self.REPR_DAYS, rule=_mass_flow_pos) self.block.ineq_mass_flow_neg = Constraint(self.TIME, self.REPR_DAYS, rule=_mass_flow_neg) def _eq_heat_loss(b, t, c=None): if self.repr_days is None: return b.heat_loss_tot[t] * (self.hl_setting * b.mass_flow_max) == b.heat_loss_nom[t] * \ b.mass_flow_abs[t] * self.length else: return b.heat_loss_tot[t, c] * (self.hl_setting * b.mass_flow_max) == b.heat_loss_nom[t, c] * \ b.mass_flow_abs[t, c] * self.length if self.repr_days is None: self.block.eq_heat_loss = Constraint(self.TIME, rule=_eq_heat_loss) else: self.block.eq_heat_loss = Constraint(self.TIME, self.REPR_DAYS, rule=_eq_heat_loss) self.construct_pumping_constraints() self.logger.info('Optimization model Pipe {} compiled'.format( self.name)) self.compiled = True self.logger.debug('========================') self.logger.debug(self.name) self.logger.debug('DN:', str(self.dn))
def acm(m, k): return m.M[0, k] == m.M_ic[k] def acx(m, k): return m.x[0, k] == m.x_ic[k] # --------------------------------------------------------------------------------------------------------------------- mod = ConcreteModel() mod.t = ContinuousSet(bounds=(0, 1)) mod.Ntray = Ntray = 42 mod.tray = Set(initialize=[i for i in range(1, mod.Ntray + 1)]) mod.feed = Param(mod.tray, initialize=lambda m, k: 57.5294 if k == 21 else 0.0, mutable=True) mod.xf = Param(initialize=0.32, mutable=True) # feed mole fraction mod.hf = Param(initialize=9081.3) # feed enthalpy mod.hlm0 = Param(initialize=2.6786e-04) mod.hlma = Param(initialize=-0.14779) mod.hlmb = Param(initialize=97.4289) mod.hlmc = Param(initialize=-2.1045e04) mod.hln0 = Param(initialize=4.0449e-04) mod.hlna = Param(initialize=-0.1435) mod.hlnb = Param(initialize=121.7981) mod.hlnc = Param(initialize=-3.0718e04)
def coefficient_matching(model, constraint, uncertain_params, config): ''' :param model: master problem model :param constraint: the constraint from the master problem model :param uncertain_params: the list of uncertain parameters :param first_stage_variables: the list of effective first-stage variables (includes ssv if decision_rule_order = 0) :return: True if the coefficient matching was successful, False if its proven robust_infeasible due to constraints of the form 1 == 0 ''' # === Returned flags successful_matching = True robust_infeasible = False # === Efficiency for q_LB = q_UB actual_uncertain_params = [] for i in range(len(uncertain_params)): if not is_certain_parameter(uncertain_param_index=i, config=config): actual_uncertain_params.append(uncertain_params[i]) # === Add coefficient matching constraint list if not hasattr(model, "coefficient_matching_constraints"): model.coefficient_matching_constraints = ConstraintList() if not hasattr(model, "swapped_constraints"): model.swapped_constraints = ConstraintList() variables_in_constraint = ComponentSet(identify_variables(constraint.expr)) params_in_constraint = ComponentSet(identify_mutable_parameters(constraint.expr)) first_stage_variables = model.util.first_stage_variables second_stage_variables = model.util.second_stage_variables # === Determine if we need to do DR expression/ssv substitution to # make h(x,z,q) == 0 into h(x,d,q) == 0 (which is just h(x,q) == 0) if all(v in ComponentSet(first_stage_variables) for v in variables_in_constraint) and \ any(q in ComponentSet(actual_uncertain_params) for q in params_in_constraint): # h(x, q) == 0 pass elif all(v in ComponentSet(first_stage_variables + second_stage_variables) for v in variables_in_constraint) and \ any(q in ComponentSet(actual_uncertain_params) for q in params_in_constraint): constraint = substitute_ssv_in_dr_constraints(model=model, constraint=constraint) variables_in_constraint = ComponentSet(identify_variables(constraint.expr)) params_in_constraint = ComponentSet(identify_mutable_parameters(constraint.expr)) else: pass if all(v in ComponentSet(first_stage_variables) for v in variables_in_constraint) and \ any(q in ComponentSet(actual_uncertain_params) for q in params_in_constraint): # Swap param objects for variable objects in this constraint model.param_set = [] for i in range(len(list(variables_in_constraint))): # Initialize Params to non-zero value due to standard_repn bug model.add_component("p_%s" % i, Param(initialize=1, mutable=True)) model.param_set.append(getattr(model, "p_%s" % i)) model.variable_set = [] for i in range(len(list(actual_uncertain_params))): model.add_component("x_%s" % i, Var(initialize=1)) model.variable_set.append(getattr(model, "x_%s" % i)) original_var_to_param_map = list(zip(list(variables_in_constraint), model.param_set)) original_param_to_vap_map = list(zip(list(actual_uncertain_params), model.variable_set)) var_to_param_substitution_map_forward = {} # Separation problem initialized to nominal uncertain parameter values for var, param in original_var_to_param_map: var_to_param_substitution_map_forward[id(var)] = param param_to_var_substitution_map_forward = {} # Separation problem initialized to nominal uncertain parameter values for param, var in original_param_to_vap_map: param_to_var_substitution_map_forward[id(param)] = var var_to_param_substitution_map_reverse = {} # Separation problem initialized to nominal uncertain parameter values for var, param in original_var_to_param_map: var_to_param_substitution_map_reverse[id(param)] = var param_to_var_substitution_map_reverse = {} # Separation problem initialized to nominal uncertain parameter values for param, var in original_param_to_vap_map: param_to_var_substitution_map_reverse[id(var)] = param model.swapped_constraints.add( replace_expressions( expr=replace_expressions(expr=constraint.lower, substitution_map=param_to_var_substitution_map_forward), substitution_map=var_to_param_substitution_map_forward) == replace_expressions( expr=replace_expressions(expr=constraint.body, substitution_map=param_to_var_substitution_map_forward), substitution_map=var_to_param_substitution_map_forward)) swapped = model.swapped_constraints[max(model.swapped_constraints.keys())] val = generate_standard_repn(swapped.body, compute_values=False) if val.constant is not None: if type(val.constant) not in native_types: temp_expr = replace_expressions(val.constant, substitution_map=var_to_param_substitution_map_reverse) if temp_expr.is_potentially_variable(): model.coefficient_matching_constraints.add(expr=temp_expr == 0) elif math.isclose(value(temp_expr), 0, rel_tol=COEFF_MATCH_REL_TOL, abs_tol=COEFF_MATCH_ABS_TOL): pass else: successful_matching = False robust_infeasible = True elif math.isclose(value(val.constant), 0, rel_tol=COEFF_MATCH_REL_TOL, abs_tol=COEFF_MATCH_ABS_TOL): pass else: successful_matching = False robust_infeasible = True if val.linear_coefs is not None: for coeff in val.linear_coefs: if type(coeff) not in native_types: temp_expr = replace_expressions(coeff, substitution_map=var_to_param_substitution_map_reverse) if temp_expr.is_potentially_variable(): model.coefficient_matching_constraints.add(expr=temp_expr == 0) elif math.isclose(value(temp_expr), 0, rel_tol=COEFF_MATCH_REL_TOL, abs_tol=COEFF_MATCH_ABS_TOL): pass else: successful_matching = False robust_infeasible = True elif math.isclose(value(coeff), 0, rel_tol=COEFF_MATCH_REL_TOL, abs_tol=COEFF_MATCH_ABS_TOL): pass else: successful_matching = False robust_infeasible = True if val.quadratic_coefs: for coeff in val.quadratic_coefs: if type(coeff) not in native_types: temp_expr = replace_expressions(coeff, substitution_map=var_to_param_substitution_map_reverse) if temp_expr.is_potentially_variable(): model.coefficient_matching_constraints.add(expr=temp_expr == 0) elif math.isclose(value(temp_expr), 0, rel_tol=COEFF_MATCH_REL_TOL, abs_tol=COEFF_MATCH_ABS_TOL): pass else: successful_matching = False robust_infeasible = True elif math.isclose(value(coeff), 0, rel_tol=COEFF_MATCH_REL_TOL, abs_tol=COEFF_MATCH_ABS_TOL): pass else: successful_matching = False robust_infeasible = True if val.nonlinear_expr is not None: successful_matching = False robust_infeasible = False if successful_matching: model.util.h_x_q_constraints.add(constraint) for i in range(len(list(variables_in_constraint))): model.del_component("p_%s" % i) for i in range(len(list(params_in_constraint))): model.del_component("x_%s" % i) model.del_component("swapped_constraints") model.del_component("swapped_constraints_index") return successful_matching, robust_infeasible
def construct_pumping_constraints(self): """ Construct a set of constraints :param n_segments: How many linear segments should be used to approximate the pumping power curve :return: """ if self.dn is not 0: di = self.di[self.dn] else: di = 1 if self.compiled: for n in self.n_pump: if self.dn is not 0: self.block.pps[n] = 2 * self.f * self.length * ( self.mfs_ratio[n] * self.mflo_max)**3 * 8 / (di**5 * 983**2 * pi**2) else: self.block.pps[n] = 0 else: n_segments = self.n_pump_constr self.n_pump = range(n_segments + 1) self.mfs_ratio = np.linspace(0, 1, n_segments + 1) self.block.pps = Param(self.n_pump, mutable=True) for n in self.n_pump: if self.dn is not 0: self.block.pps[n] = 2 * self.f * self.length * ( self.mfs_ratio[n] * self.mflo_max)**3 * 8 / (di**5 * 983**2 * pi**2) else: self.block.pps[n] = 0 if self.repr_days: self.block.pumping_power = Var(self.TIME, self.REPR_DAYS, within=NonNegativeReals) else: self.block.pumping_power = Var(self.TIME, within=NonNegativeReals) for i in range(n_segments): def _ineq_pumping(b, t, c=None): if self.repr_days is None: return b.pumping_power[t] * b.mass_flow_max >= ( b.mass_flow_abs[t] - b.mass_flow_max * self.mfs_ratio[i]) / ( self.mfs_ratio[i + 1] - self.mfs_ratio[i]) * ( b.pps[i + 1] - b.pps[i]) + b.mass_flow_max * b.pps[i] else: return b.pumping_power[t, c] * b.mass_flow_max >= ( b.mass_flow_abs[t, c] - b.mass_flow_max * self.mfs_ratio[i]) / ( self.mfs_ratio[i + 1] - self.mfs_ratio[i]) * ( b.pps[i + 1] - b.pps[i]) + b.mass_flow_max * b.pps[i] if self.repr_days is None: self.block.add_component( 'ineq_pumping_' + str(i), Constraint(self.TIME, rule=_ineq_pumping)) else: self.block.add_component( 'ineq_pumping_' + str(i), Constraint(self.TIME, self.REPR_DAYS, rule=_ineq_pumping))
from pyomo.core.base import AbstractModel, Set, PositiveIntegers, Param, Var, Constraint, Objective, \ ConcreteModel, NonNegativeReals, value, maximize model = AbstractModel() # Nodes in the network model.N = Set() # Network arcs model.A = Set(within=model.N*model.N) # Source node model.s = Param(within=model.N) # Sink node model.t = Param(within=model.N) # Flow capacity limits model.c = Param(model.A) # The flow over each arc model.f = Var(model.A, within=NonNegativeReals) # Maximize the flow into the sink nodes def total_rule(model): return sum(model.f[i,j] for (i, j) in model.A if j == value(model.t)) model.total = Objective(rule=total_rule, sense=maximize) # Enforce an upper limit on the flow across each arc def limit_rule(model, i, j): return model.f[i,j] <= model.c[i, j] model.limit = Constraint(model.A, rule=limit_rule) # Enforce flow through each node
def __init__(self, nfe_t, ncp_t, **kwargs): #: type: (int, int, dict) #: if steady == True fallback to steady-state computation self.nfe_t = nfe_t #: self.ncp_t = ncp_t self.scheme = kwargs.pop('scheme', 'LAGRANGE-RADAU') self.steady = kwargs.pop('steady', False) self._t = kwargs.pop('_t', 1.0) ncstr = kwargs.pop('n_cstr', 1) ConcreteModel.__init__(self) self.ncstr = Set(initialize=[i for i in range(0, ncstr)]) if self.steady: self.t = Set(initialize=[1]) else: self.t = ContinuousSet(bounds=(0, self._t)) self.Cainb = Param(default=1.0) self.Tinb = Param(default=275.0) self.Tjinb = Param(default=250.0) self.V = Param(initialize=100) self.UA = Param(initialize=20000 * 60) self.rho = Param(initialize=1000) self.Cp = Param(initialize=4.2) self.Vw = Param(initialize=10) self.rhow = Param(initialize=1000) self.Cpw = Param(initialize=4.2) self.k0 = Param(initialize=4.11e13) self.E = Param(initialize=76534.704) self.R = Param(initialize=8.314472) self.Er = Param(initialize=lambda m: (value(self.E) / value(self.R))) self.dH = Param(initialize=596619.) self.F = Param(self.t, mutable=True, default=1.2000000000000000E+02) self.Fw = Param(self.t, mutable=True, default=3.0000000000000000E+01) # States self.Ca = Var(self.t, self.ncstr, initialize=1.60659680385930765667001907104350E-02) self.T = Var(self.t, self.ncstr, initialize=3.92336059452774350120307644829154E+02) self.Tj = Var(self.t, self.ncstr, initialize=3.77995395658401662331016268581152E+02) self.k = Var(self.t, self.ncstr, initialize=4.70706140E+02) self.kdef = Constraint(self.t, self.ncstr) #: These guys have to be zero at the steady-state (steady). zero0 = dict.fromkeys(self.t * self.ncstr) for key in zero0.keys(): zero0[key] = 0.0 if self.steady: self.Cadot = zero0 self.Tdot = zero0 self.Tjdot = zero0 else: self.Cadot = DerivativeVar(self.Ca, initialize=-3.58709135E+01) self.Tdot = DerivativeVar(self.T, initialize=5.19191848E+03) self.Tjdot = DerivativeVar(self.Tj, initialize=-9.70467399E+02) #: These guys as well (steady). self.Ca_ic = Param(self.ncstr, default=1.9193793974995963E-02) self.T_ic = Param(self.ncstr, default=3.8400724261199036E+02) self.Tj_ic = Param(self.ncstr, default=3.7127352272578315E+02) # m.Ca_ic = Param(m.ncstr, default=1.9193793974995963E-02) # m.T_ic = Param(m.ncstr, default=3.8400724261199036E+02) # m.Tj_ic = Param(m.ncstr, default=3.7127352272578315E+02) self.ODE_ca = Constraint(self.t, self.ncstr) self.ODE_T = Constraint(self.t, self.ncstr) self.ODE_Tj = Constraint(self.t, self.ncstr) #: No need of these guys at steady. if self.steady: self.Ca_icc = None self.T_icc = None self.Tj_icc = None else: self.Ca_icc = Constraint(self.ncstr) self.T_icc = Constraint(self.ncstr) self.Tj_icc = Constraint(self.ncstr) def _rule_k(m, i, n): if i == 0: return Constraint.Skip else: return m.k[i, n] == m.k0 * exp(-m.Er / m.T[i, n]) def _rule_ca(m, i, n): if i == 0: return Constraint.Skip else: rule = m.Cadot[i, n] == (m.F[i] / m.V) * (m.Cainb - m.Ca[i, n]) - 2 * m.k[i, n] * m.Ca[i, n] ** 2 return rule def _rule_t(m, i, n): if i == 0: return Constraint.Skip else: return m.Tdot[i, n] == (m.F[i] / m.V) * (m.Tinb - m.T[i, n]) + \ 2.0 * m.dH / (m.rho * m.Cp) * m.k[i, n] * m.Ca[i, n] ** 2 -\ m.UA / (m.V * m.rho * m.Cp) * (m.T[i, n] - m.Tj[i, n]) def _rule_tj(m, i, n): if i == 0: return Constraint.Skip else: return m.Tjdot[i, n] == \ (m.Fw[i] / m.Vw) * (m.Tjinb - m.Tj[i, n]) + m.UA / (m.Vw * m.rhow * m.Cpw) * (m.T[i, n] - m.Tj[i, n]) def _rule_ca0(m, n): return m.Ca[0, n] == m.Ca_ic[n] def _rule_t0(m, n): return m.T[0, n] == m.T_ic[n] def _rule_tj0(m, n): return m.Tj[0, n] == m.Tj_ic[n] # let Ca0 := 1.9193793974995963E-02 ; # let T0 := 3.8400724261199036E+02 ; # let Tj0 := 3.7127352272578315E+02 ; self.kdef.rule = lambda m, i, n: _rule_k(m, i, n) self.ODE_ca.rule = lambda m, i, n: _rule_ca(m, i, n) self.ODE_T.rule = lambda m, i, n: _rule_t(m, i, n) self.ODE_Tj.rule = lambda m, i, n: _rule_tj(m, i, n) if self.steady: pass else: self.Ca_icc.rule = lambda m, n: _rule_ca0(m, n) self.T_icc.rule = lambda m, n: _rule_t0(m, n) self.Tj_icc.rule = lambda m, n: _rule_tj0(m, n) self.Ca_icc.reconstruct() self.T_icc.reconstruct() self.Tj_icc.reconstruct() self.kdef.reconstruct() self.ODE_ca.reconstruct() self.ODE_T.reconstruct() self.ODE_Tj.reconstruct() # Declare at framework level self.dual = Suffix(direction=Suffix.IMPORT_EXPORT) self.ipopt_zL_out = Suffix(direction=Suffix.IMPORT) self.ipopt_zU_out = Suffix(direction=Suffix.IMPORT) self.ipopt_zL_in = Suffix(direction=Suffix.EXPORT) self.ipopt_zU_in = Suffix(direction=Suffix.EXPORT) self.discretizer = TransformationFactory('dae.collocation')
def dist_col_Rodrigo_ss(init0, bnd_set): # collocation polynomial parameters # polynomial roots (Radau) m = ConcreteModel() m.i_flag = init0 # set of finite elements and collocation points m.fe = Set(initialize=[1]) m.cp = Set(initialize=[1]) m.bnd_set = bnd_set if bnd_set: print("Bounds_set") Ntray = 42 m.Ntray = Ntray m.tray = Set(initialize=[i for i in range(1, Ntray + 1)]) def __init_feed(m, t): if t == 21: return 57.5294 else: return 0 m.feed = Param(m.tray, initialize=__init_feed) m.xf = Param(initialize=0.32) # feed mole fraction m.hf = Param(initialize=9081.3) # feed enthalpy m.hlm0 = Param(initialize=2.6786e-04) m.hlma = Param(initialize=-0.14779) m.hlmb = Param(initialize=97.4289) m.hlmc = Param(initialize=-2.1045e04) m.hln0 = Param(initialize=4.0449e-04) m.hlna = Param(initialize=-0.1435) m.hlnb = Param(initialize=121.7981) m.hlnc = Param(initialize=-3.0718e04) m.r = Param(initialize=8.3147) m.a = Param(initialize=6.09648) m.b = Param(initialize=1.28862) m.c1 = Param(initialize=1.016) m.d = Param(initialize=15.6875) m.l = Param(initialize=13.4721) m.f = Param(initialize=2.615) m.gm = Param(initialize=0.557) m.Tkm = Param(initialize=512.6) m.Pkm = Param(initialize=8.096e06) m.gn = Param(initialize=0.612) m.Tkn = Param(initialize=536.7) m.Pkn = Param(initialize=5.166e06) m.CapAm = Param(initialize=23.48) m.CapBm = Param(initialize=3626.6) m.CapCm = Param(initialize=-34.29) m.CapAn = Param(initialize=22.437) m.CapBn = Param(initialize=3166.64) m.CapCn = Param(initialize=-80.15) m.pstrip = Param(initialize=250) m.prect = Param(initialize=190) def _p_init(m, t): ptray = 9.39e04 if t <= 20: return _p_init(m, 21) + m.pstrip * (21 - t) elif 20 < t < m.Ntray: return ptray + m.prect * (m.Ntray - t) elif t == m.Ntray: return 9.39e04 m.p = Param(m.tray, initialize=_p_init) m.T29_des = Param(initialize=343.15) m.T15_des = Param(initialize=361.15) m.Dset = Param(initialize=1.83728) m.Qcset = Param(initialize=1.618890) m.Qrset = Param(initialize=1.786050) m.Recset = Param() m.alpha_T29 = Param(initialize=1) m.alpha_T15 = Param(initialize=1) m.alpha_D = Param(initialize=1) m.alpha_Qc = Param(initialize=1) m.alpha_Qr = Param(initialize=1) m.alpha_Rec = Param(initialize=1) def _alpha_init(m, i): if i <= 21: return 0.62 else: return 0.35 m.alpha = Param(m.tray, initialize=_alpha_init) ME0 = {} ME0[1] = 123790.826443232 ME0[2] = 3898.34923206106 ME0[3] = 3932.11766868415 ME0[4] = 3950.13107445914 ME0[5] = 3960.01212104318 ME0[6] = 3965.37146944881 ME0[7] = 3968.25340380767 ME0[8] = 3969.78910997468 ME0[9] = 3970.5965548502 ME0[10] = 3971.0110096803 ME0[11] = 3971.21368740283 ME0[12] = 3971.30232788932 ME0[13] = 3971.32958547037 ME0[14] = 3971.32380573089 ME0[15] = 3971.30024105555 ME0[16] = 3971.26709591428 ME0[17] = 3971.22878249852 ME0[18] = 3971.187673073 ME0[19] = 3971.14504284211 ME0[20] = 3971.10157713182 ME0[21] = 3971.05764415189 ME0[22] = 3611.00216267141 ME0[23] = 3766.84741932423 ME0[24] = 3896.87907072814 ME0[25] = 4004.98630195624 ME0[26] = 4092.49383654928 ME0[27] = 4161.86560059956 ME0[28] = 4215.98509169956 ME0[29] = 4257.69470716792 ME0[30] = 4289.54901779038 ME0[31] = 4313.71557755738 ME0[32] = 4331.9642075775 ME0[33] = 4345.70190802884 ME0[34] = 4356.02621744716 ME0[35] = 4363.78165047072 ME0[36] = 4369.61159802674 ME0[37] = 4374.00266939603 ME0[38] = 4377.32093116489 ME0[39] = 4379.84068162411 ME0[40] = 4381.76685527968 ME0[41] = 4383.25223100374 ME0[42] = 4736.04924276762 m.M_pred = Param(m.tray, initialize=ME0) XE0 = {} XE0[1] = 0.306547877605746 XE0[2] = 0.398184778678485 XE0[3] = 0.416675004386508 XE0[4] = 0.42676332128531 XE0[5] = 0.432244548463899 XE0[6] = 0.435193762178033 XE0[7] = 0.436764699693985 XE0[8] = 0.437589297877498 XE0[9] = 0.438010896454752 XE0[10] = 0.43821522113022 XE0[11] = 0.438302495819782 XE0[12] = 0.438326730875504 XE0[13] = 0.438317008813347 XE0[14] = 0.438288981487008 XE0[15] = 0.438251069561153 XE0[16] = 0.438207802087721 XE0[17] = 0.438161614415035 XE0[18] = 0.438113815737636 XE0[19] = 0.438065109638753 XE0[20] = 0.438015874079915 XE0[21] = 0.437966311972983 XE0[22] = 0.724835538043496 XE0[23] = 0.788208485334881 XE0[24] = 0.838605564838572 XE0[25] = 0.87793558673077 XE0[26] = 0.908189470853012 XE0[27] = 0.931224584141055 XE0[28] = 0.948635083197147 XE0[29] = 0.961724712952285 XE0[30] = 0.971527857048483 XE0[31] = 0.978848914860811 XE0[32] = 0.984304939392599 XE0[33] = 0.98836476845163 XE0[34] = 0.991382214572503 XE0[35] = 0.993622983870866 XE0[36] = 0.995285909293636 XE0[37] = 0.996519395295701 XE0[38] = 0.997433995899531 XE0[39] = 0.998111951760656 XE0[40] = 0.998614376770054 XE0[41] = 0.998986649363 XE0[42] = 0.999262443919619 m.x_pred = Param(m.tray, initialize=XE0) # hold in each tray def __m_init(m, i, j, t): if m.i_flag: if t < m.Ntray: return 4000. elif t == 1: return 104340. elif t == m.Ntray: return 5000. else: return 0. m.M = Var(m.fe, m.cp, m.tray, initialize=__m_init) # m.M_0 = Var(m.fe, m.tray, initialize=1e07) # temperatures def __t_init(m, i, j, t): if m.i_flag: return ((370.781 - 335.753) / m.Ntray) * t + 370.781 else: return 10. m.T = Var(m.fe, m.cp, m.tray, initialize=__t_init) # saturation pressures m.pm = Var(m.fe, m.cp, m.tray, initialize=1e4) m.pn = Var(m.fe, m.cp, m.tray, initialize=1e4) # define l-v flowrate def _v_init(m, i, j, t): if m.i_flag: return 44. else: return 0. m.V = Var(m.fe, m.cp, m.tray, initialize=_v_init) def _l_init(m, i, j, t): if m.i_flag: if 2 <= t <= 21: return 83. elif 22 <= t <= 42: return 23 elif t == 1: return 40 else: return 0. m.L = Var(m.fe, m.cp, m.tray, initialize=_l_init) # mol frac l-v def __x_init(m, i, j, t): if m.i_flag: return (0.999 / m.Ntray) * t else: return 1 m.x = Var(m.fe, m.cp, m.tray, initialize=__x_init) #m.x_0 = Var(m.fe, m.tray) # av def __y_init(m, i, j, t): if m.i_flag: return ((0.99 - 0.005) / m.Ntray) * t + 0.005 else: return 1 m.y = Var(m.fe, m.cp, m.tray, initialize=__y_init) # enthalpy m.hl = Var(m.fe, m.cp, m.tray, initialize=10000.) def __hv_init(m, i, j, t): if m.i_flag: if t < m.Ntray: return 5e4 else: return 0.0 m.hv = Var(m.fe, m.cp, m.tray, initialize=__hv_init) # reboiler & condenser heat m.Qc = Var(m.fe, m.cp, initialize=1.6e06) m.D = Var(m.fe, m.cp, initialize=18.33) # vol holdups m.Vm = Var(m.fe, m.cp, m.tray, initialize=6e-05) def __mv_init(m, i, j, t): if m.i_flag: if 1 < t < m.Ntray: return 0.23 else: return 0.0 m.Mv = Var(m.fe, m.cp, m.tray, initialize=__mv_init) m.Mv1 = Var(m.fe, m.cp, initialize=8.57) m.Mvn = Var(m.fe, m.cp, initialize=0.203) def _bound_set(m): if m.bnd_set: for key, value in m.M.iteritems(): value.setlb(1.0) value.setub(1e7) for key, value in m.Vm.iteritems(): value.setlb(-1.0) value.setub(1e4) for key, value in m.Mv.iteritems(): value.setlb(0.155 + 1e-06) value.setub(1e4) for key, value in m.Mv1.iteritems(): value.setlb(8.5 + 1e-06) value.setub(1e4) for key, value in m.Mvn.iteritems(): value.setlb(0.17 + 1e-06) value.setub(1e4) for key, value in m.y.iteritems(): value.setlb(0.0) value.setub(1.0) for key, value in m.x.iteritems(): value.setlb(0.0) value.setub(1.0) for key, value in m.L.iteritems(): value.setlb(0.0) for key, value in m.V.iteritems(): value.setlb(0.0) _bound_set(m) m.Rec = Param(m.fe, initialize=7.72700925775773761472464684629813e-01) # m.Rec = Param(m.fe, initialize=0.05) m.Qr = Param(m.fe, initialize=1.78604740940007800236344337463379E+06) # m.Qr = Param(m.fe, initialize=1.5e+02) # mass balances def _MODEtr(m, i, j, k): if j > 0 and 1 < k < Ntray: return 0.0 == (m.V[i, j, k - 1] - m.V[i, j, k] + m.L[i, j, k + 1] - m.L[i, j, k] + m.feed[k]) else: return Constraint.Skip m.MODEtr = Constraint(m.fe, m.cp, m.tray, rule=_MODEtr) # m.L[i, j, 1] = B def _MODEr(m, i, j): if j > 0: return 0.0 == (m.L[i, j, 2] - m.L[i, j, 1] - m.V[i, j, 1]) else: return Constraint.Skip m.MODEr = Constraint(m.fe, m.cp, rule=_MODEr) def _MODEc(m, i, j): if j > 0: return 0.0 == (m.V[i, j, Ntray - 1] - m.L[i, j, Ntray] - m.D[i, j]) else: return Constraint.Skip m.MODEc = Constraint(m.fe, m.cp, rule=_MODEc) def _XODEtr(m, i, j, t): if j > 0 and 1 < t < Ntray: return 0.0 == (m.V[i, j, t - 1] * (m.y[i, j, t - 1] - m.x[i, j, t]) + \ m.L[i, j, t + 1] * (m.x[i, j, t + 1] - m.x[i, j, t]) - \ m.V[i, j, t] * (m.y[i, j, t] - m.x[i, j, t]) + \ m.feed[t] * (m.xf - m.x[i, j, t])) else: return Constraint.Skip m.XODEtr = Constraint(m.fe, m.cp, m.tray, rule=_XODEtr) def _xoder(m, i, j): if j > 0: return 0.0 == (m.L[i, j, 2] * (m.x[i, j, 2] - m.x[i, j, 1]) - \ m.V[i, j, 1] * (m.y[i, j, 1] - m.x[i, j, 1])) else: return Constraint.Skip m.xoder = Constraint(m.fe, m.cp, rule=_xoder) def _xodec(m, i, j): if j > 0: return 0.0 == \ (m.V[i, j, Ntray - 1] * (m.y[i, j, Ntray - 1] - m.x[i, j, Ntray])) else: return Constraint.Skip m.xodec = Constraint(m.fe, m.cp, rule=_xodec) def _hrc(m, i, j): if j > 0: return m.D[i, j] - m.Rec[i] * m.L[i, j, Ntray] == 0 else: return Constraint.Skip m.hrc = Constraint(m.fe, m.cp, rule=_hrc) # Energy balance def _gh(m, i, j, t): if j > 0 and 1 < t < Ntray: return 0.0 \ == (m.V[i, j, t-1] * (m.hv[i, j, t-1] - m.hl[i, j, t]) + m.L[i, j, t+1] * (m.hl[i, j, t+1] - m.hl[i, j, t]) - m.V[i, j, t] * (m.hv[i, j, t] - m.hl[i, j, t]) + m.feed[t] * (m.hf - m.hl[i, j, t])) # return m.M[i, j, t] * (m.xdot[i, j, t] * ((m.hlm0 - m.hln0) * m.T[i, j, t]**3 + (m.hlma - m.hlna) * m.T[i, j, t]**2 + (m.hlmb - m.hlnb) * m.T[i, j, t] + m.hlmc - m.hlnc) + m.Tdot[i, j, t]*(3*m.hln0*m.T[i, j, t]**2 + 2*m.hlna * m.T[i, j, t] + m.hlnb + m.x[i, j, t]*(3*(m.hlm0 - m.hln0) * m.T[i, j, t]**2 + 2 * (m.hlma - m.hlna) * m.T[i, j, t] + m.hlmb - m.hlnb))) \ # M[i, q, c] * ( xdot[i, q, c] * (( hlm0 - hln0) * T[i, q, c] ^ 3 + ( hlma - hlna) * T[i, q, c] ^ 2 + ( hlmb - hlnb) * T[i, q, c] + hlmc - hlnc) + Tdot[i, q, c]*(3* hln0 * T[i, q, c] ^ 2 +2 * hlna * T[i, q, c] + hlnb + x[i, q, c]*(3*( hlm0 - hln0) * T[i, q, c] ^ 2 + 2 * ( hlma - hlna) * T[i, q, c] + hlmb - hlnb))) = # V[i - 1, q, c]*(hv[i - 1, q, c] - hl[i, q, c]) + L[i + 1, q, c]*(hl[i + 1, q, c] - hl[i, q, c]) - V[i, q, c] * ( hv[i, q, c] - hl[i, q, c]) + feed[i] * ( hf - hl[i, q, c]); else: return Constraint.Skip # M[i,q,c] *( xdot[i,q,c]* ((hlm0 - hln0) * T[i,q,c]^3 + ( hlma - hlna) * T[i,q,c]^2 + ( hlmb - hlnb) * T[i,q,c] + hlmc - hlnc) + Tdot[i,q,c] *(3* hln0* T[i,q,c]^2 + 2* hlna* T[i,q,c] + hlnb + x[i,q,c]* (3*( hlm0 - hln0) *T[i,q,c]^2 + 2* (hlma - hlna) *T[i,q,c]+ hlmb - hlnb))) # V[i-1,q,c] *( hv[i-1,q,c] - hl[i,q,c] ) + L[i+1,q,c]* ( hl[i+1,q,c] - hl[i,q,c] ) - V[i,q,c] * ( hv[i,q,c] - hl[i,q,c]) + feed[i] * (hf - hl[i,q,c]) m.gh = Constraint(m.fe, m.cp, m.tray, rule=_gh) def _ghb(m, i, j): if j > 0: return 0.0 == \ (m.L[i, j, 2] * (m.hl[i, j, 2] - m.hl[i, j, 1]) - m.V[i, j, 1] * (m.hv[i, j, 1] - m.hl[i, j, 1]) + m.Qr[i]) # M[1,q,c]* ( xdot[1,q,c] * (( hlm0 - hln0) *T[1,q,c]^3 + (hlma - hlna)* T[1,q,c]^2 + ( hlmb - hlnb) *T[1,q,c] + hlmc - hlnc) + Tdot[1,q,c]* (3* hln0 * T[1,q,c]^2 + 2 * hlna * T[1,q,c] + hlnb + x[1,q,c] * (3 * ( hlm0 - hln0) * T[1,q,c]^2 + 2*( hlma - hlna) *T[1,q,c] + hlmb - hlnb))) = # L[2,q,c]* ( hl[2,q,c] - hl[1,q,c] ) - V[1,q,c] * ( hv[1,q,c] - hl[1,q,c] ) + Qr[q] ; else: return Constraint.Skip m.ghb = Constraint(m.fe, m.cp, rule=_ghb) def _ghc(m, i, j): if j > 0: return 0.0 == \ (m.V[i, j, Ntray - 1] * (m.hv[i, j, Ntray - 1] - m.hl[i, j, Ntray]) - m.Qc[i, j]) #M[Ntray, q, c] * (xdot[Ntray, q, c] * ((hlm0 - hln0) * T[Ntray, q, c] ^ 3 + (hlma - hlna) * T[Ntray, q, c] ^ 2 + (hlmb - hlnb) * T[Ntray, q, c] + hlmc - hlnc) + Tdot[Ntray, q, c] * (3 * hln0 * T[Ntray, q, c] ^ 2 + 2 * hlna * T[Ntray, q, c] + hlnb + x[Ntray, q, c] * (3 * ( hlm0 - hln0) * T[Ntray, q, c] ^ 2 + 2 * (hlma - hlna) * T[Ntray, q, c] + hlmb - hlnb))) = # V[Ntray - 1, q, c] * (hv[Ntray - 1, q, c] - hl[Ntray, q, c]) - Qc[q, c]; else: return Constraint.Skip #M[Ntray, q, c] * ( xdot[Ntray, q, c] * (( hlm0 - hln0) * T[Ntray, q, c] ^ 3 + ( hlma - hlna) * T[Ntray, q, c] ^ 2 +(hlmb - hlnb) * T[Ntray, q, c] + hlmc - hlnc) + Tdot[Ntray, q, c] * (3 * hln0 * T[Ntray, q, c] ^ 2 + 2 * hlna * T[Ntray, q, c] + hlnb + x[Ntray, q, c] * (3 * ( hlm0 - hln0) * T[Ntray, q, c] ^ 2 + 2 * (hlma - hlna) * T[Ntray, q, c] + hlmb - hlnb))) = # V[Ntray - 1, q, c] * (hv[Ntray - 1, q, c] - hl[Ntray, q, c]) - Qc[q, c]; m.ghc = Constraint(m.fe, m.cp, rule=_ghc) def _hkl(m, i, j, t): if j > 0: return m.hl[i, j, t] == m.x[i, j, t] * ( m.hlm0 * m.T[i, j, t]**3 + m.hlma * m.T[i, j, t]**2 + m.hlmb * m.T[i, j, t] + m.hlmc) + (1 - m.x[i, j, t]) * ( m.hln0 * m.T[i, j, t]**3 + m.hlna * m.T[i, j, t]**2 + m.hlnb * m.T[i, j, t] + m.hlnc) # hl[i, q, c] = x[i, q, c]*( hlm0 * T[i, q, c] ^ 3 + hlma * T[i, q, c] ^ 2 + hlmb * T[i, q, c] + hlmc ) + (1 - x[i, q, c] )*( hln0 * T[i, q, c] ^ 3 + hlna* T[i, q, c] ^ 2 + hlnb * T[i, q, c] + hlnc); else: return Constraint.Skip # hl[i,q,c] = x[i,q,c]* ( hlm0* T[i,q,c]^3 + hlma * T[i,q,c]^2 + hlmb* T[i,q,c] + hlmc) + (1 - x[i,q,c])* ( hln0 *T[i,q,c] ^ 3 + hlna* T[i,q,c]^2 + hlnb *T[i,q,c] + hlnc) ; m.hkl = Constraint(m.fe, m.cp, m.tray, rule=_hkl) def _hkv(m, i, j, t): if j > 0 and t < Ntray: return m.hv[i, j, t] == m.y[i, j, t] * ( m.hlm0 * m.T[i, j, t]**3 + m.hlma * m.T[i, j, t]**2 + m.hlmb * m.T[i, j, t] + m.hlmc + m.r * m.Tkm * sqrt(1 - (m.p[t] / m.Pkm) * (m.Tkm / m.T[i, j, t])**3) * (m.a - m.b * m.T[i, j, t] / m.Tkm + m.c1 * (m.T[i, j, t] / m.Tkm)**7 + m.gm * (m.d - m.l * m.T[i, j, t] / m.Tkm + m.f * (m.T[i, j, t] / m.Tkm)**7))) + (1 - m.y[i, j, t]) * ( m.hln0 * m.T[i, j, t]**3 + m.hlna * m.T[i, j, t]**2 + m.hlnb * m.T[i, j, t] + m.hlnc + m.r * m.Tkn * sqrt(1 - (m.p[t] / m.Pkn) * (m.Tkn / m.T[i, j, t])**3) * (m.a - m.b * m.T[i, j, t] / m.Tkn + m.c1 * (m.T[i, j, t] / m.Tkn)**7 + m.gn * (m.d - m.l * m.T[i, j, t] / m.Tkn + m.f * (m.T[i, j, t] / m.Tkn)**7))) else: return Constraint.Skip # hv[i,q,c] = y[i,q,c] * (hlm0 * T[i,q,c]^3 + hlma* T[i,q,c]^2 + hlmb * T[i,q,c] + hlmc + r* Tkm* sqrt(1 - ( p[i]/ Pkm)* ( Tkm/ T[i,q,c]) ^ 3 )*(a - b* T[i,q,c]/ Tkm + c1* ( T[i,q,c] / Tkm) ^7 + gm* ( d - l * T[i,q,c] /Tkm + f*( T[i,q,c] / Tkm)^7 ))) + (1 - y[i,q,c] )* ( hln0 * T[i,q,c] ^3 + hlna* T[i,q,c]^ 2 + hlnb* T[i,q,c] + hlnc + r * Tkn* sqrt(1 - ( p[i]/Pkn )*( Tkn/ T[i,q,c] )^3 )*( a - b * T[i,q,c] / Tkn + c1 * ( T[i,q,c] / Tkn)^7 + gn*( d - l* T[i,q,c]/ Tkn + f*( T[i,q,c] / Tkn) ^7 ))) ; m.hkv = Constraint(m.fe, m.cp, m.tray, rule=_hkv) def _lpm(m, i, j, t): if j > 0: return m.pm[i, j, t] == exp(m.CapAm - m.CapBm / (m.T[i, j, t] + m.CapCm)) else: return Constraint.Skip m.lpm = Constraint(m.fe, m.cp, m.tray, rule=_lpm) def _lpn(m, i, j, t): if j > 0: return m.pn[i, j, t] == exp(m.CapAn - m.CapBn / (m.T[i, j, t] + m.CapCn)) else: return Constraint.Skip m.lpn = Constraint(m.fe, m.cp, m.tray, rule=_lpn) def _dp(m, i, j, t): if j > 0: return m.p[t] == m.pm[i, j, t] * m.x[i, j, t] + ( 1 - m.x[i, j, t]) * m.pn[i, j, t] else: return Constraint.Skip m.dp = Constraint(m.fe, m.cp, m.tray, rule=_dp) def _gy0(m, i, j): if j > 0: return m.y[i, j, 1] == m.x[i, j, 1] * m.pm[i, j, 1] / m.p[1] else: return Constraint.Skip m.gy0 = Constraint(m.fe, m.cp, rule=_gy0) def _gy(m, i, j, t): if j > 0 and 1 < t < Ntray: return m.y[i, j, t] == m.alpha[t] * m.x[i, j, t] * m.pm[ i, j, t] / m.p[t] + (1 - m.alpha[t]) * m.y[i, j, t - 1] #y[i, q, c] = alpha[i] * x[i, q, c] * pm[i, q, c] / p[i] + (1 - alpha[i]) * y[i - 1, q, c]; else: return Constraint.Skip m.gy = Constraint(m.fe, m.cp, m.tray, rule=_gy) def _dMV(m, i, j, t): if j > 0 and 1 < t < Ntray: return m.Mv[i, j, t] == m.Vm[i, j, t] * m.M[i, j, t] else: return Constraint.Skip m.dMV = Constraint(m.fe, m.cp, m.tray, rule=_dMV) def _dMv1(m, i, j): if j > 0: return m.Mv1[i, j] == m.Vm[i, j, 1] * m.M[i, j, 1] else: return Constraint.Skip m.dMv1 = Constraint(m.fe, m.cp, rule=_dMv1) def _dMvn(m, i, j): if j > 0: return m.Mvn[i, j] == m.Vm[i, j, Ntray] * m.M[i, j, Ntray] else: return Constraint.Skip m.dMvn = Constraint(m.fe, m.cp, rule=_dMvn) def _hyd(m, i, j, t): if j > 0 and 1 < t < Ntray: return m.L[i, j, t] * m.Vm[i, j, t] == 0.166 * (m.Mv[i, j, t] - 0.155)**1.5 # L[i,q,c]* Vm[i,q,c] = 0.166 * ( Mv[i,q,c] - 0.155)^1.5 ; else: return Constraint.Skip m.hyd = Constraint(m.fe, m.cp, m.tray, rule=_hyd) def _hyd1(m, i, j): if j > 0: return m.L[i, j, 1] * m.Vm[i, j, 1] == 0.166 * (m.Mv1[i, j] - 8.5)**1.5 else: return Constraint.Skip # L[i,q,c]*Vm[i,q,c] = 0.166*(Mv[i,q,c] - 0.155)^1.5 ; m.hyd1 = Constraint(m.fe, m.cp, rule=_hyd1) def _hydN(m, i, j): if j > 0: return m.L[i, j, Ntray] * m.Vm[i, j, Ntray] == 0.166 * ( m.Mvn[i, j] - 0.17)**1.5 else: return Constraint.Skip # L[i,q,c]*Vm[i,q,c] = 0.166*(Mv[i,q,c] - 0.155)^1.5 ; m.hydN = Constraint(m.fe, m.cp, rule=_hydN) def _dvm(m, i, j, t): if j > 0: return m.Vm[i, j, t] == m.x[i, j, t] * ( (1 / 2288) * 0.2685** (1 + (1 - m.T[i, j, t] / 512.4)**0.2453)) + (1 - m.x[i, j, t]) * ( (1 / 1235) * 0.27136**(1 + (1 - m.T[i, j, t] / 536.4)**0.24)) else: return Constraint.Skip # Vm[i,q,c] = x[i,q,c] * ( 1/2288 * 0.2685^ (1 + (1 - T[i,q,c] /512.4)^0.2453)) + (1 - x[i,q,c]) * (1/1235 * 0.27136^ (1 + (1 - T[i,q,c] /536.4)^ 0.24)) ; m.dvm = Constraint(m.fe, m.cp, m.tray, rule=_dvm) return m
def compile(self, model, start_time): """ Build the structure of the optimization model :param model: The entire optimization model :param block:The pipe model object :param start_time: The optimization start time :return: """ Component.compile(self, model, start_time) self.history_length = len(self.params['mass_flow_history'].v()) Tg = self.params['Tg'].v() lines = self.params['lines'].v() dn = self.params['diameter'].v() time_step = self.params['time_step'].v() n_steps = int(self.params['horizon'].v() / time_step) self.block.all_time = Set(initialize=range(self.history_length + n_steps), ordered=True) pipe_wall_rho = 7.85 * 10**3 # http://www.steel-grades.com/Steel-Grades/Structure-Steel/en-p235.html kg/m^3 pipe_wall_c = 461 # http://www.steel-grades.com/Steel-Grades/Structure-Steel/en-p235.html J/kg/K pipe_wall_volume = np.pi * (self.Do[dn]**2 - self.Di[dn]**2) / 4 * self.length C = pipe_wall_volume * pipe_wall_c * pipe_wall_rho surface = np.pi * self.Di[dn]**2 / 4 # cross sectional area of the pipe Z = surface * self.rho * self.length # water mass in the pipe # TODO Move capacity? def _decl_mf(b, t): return self.params['mass_flow'].v(t) self.block.mass_flow = Param(self.TIME, rule=_decl_mf) # Declare temperature variables ################################################################################ self.block.temperatures = Var( lines, self.block.all_time) # all temperatures (historical and future) self.block.temperature_out_nhc = Var( lines, self.block.all_time) # no heat capacity (only future) self.block.temperature_out_nhl = Var( lines, self.block.all_time) # no heat losses (only future) self.block.temperature_out = Var( lines, self.block.all_time) # no heat losses (only future) self.block.temperature_in = Var( lines, self.block.all_time) # incoming temperature (future) # Declare list filled with all previous mass flows and future mass flows ####################################### def _decl_mf_history(b, t): if t < n_steps: return self.block.mass_flow[n_steps - t - 1] else: return self.params['mass_flow_history'].v(t - n_steps) self.block.mf_history = Param(self.block.all_time, rule=_decl_mf_history) # Declare list filled with all previous temperatures for every optimization step ############################### def _decl_temp_history(b, t, l): if t < n_steps: return b.temperatures[l, t] == b.temperature_in[l, n_steps - t - 1] else: return b.temperatures[l, t] == self.params['temperature_history_' + l].v(t - n_steps) self.block.def_temp_history = Constraint(self.block.all_time, lines, rule=_decl_temp_history) # Initialize incoming temperature ############################################################################## def _decl_init_temp_in(b, l): return b.temperature_in[l, 0] == self.params[ 'temperature_history_' + l].v( 0) # TODO better initialization?? self.block.decl_init_temp_in = Constraint(lines, rule=_decl_init_temp_in) # Define n ##################################################################################################### # Eq 3.4.7 def _decl_n(b, t): sum_m = 0 for i in range(len(self.block.all_time) - (n_steps - 1 - t)): sum_m += b.mf_history[n_steps - 1 - t + i] * time_step if sum_m > Z: return i self.logger.warning('A proper value for n could not be calculated') return i self.block.n = Param(self.TIME, rule=_decl_n) # Define R ##################################################################################################### # Eq 3.4.3 def _decl_r(b, t): return sum(self.block.mf_history[i] for i in range(n_steps - 1 - t, n_steps - 1 - t + b.n[t] + 1)) * time_step self.block.R = Param(self.TIME, rule=_decl_r) # Define m ##################################################################################################### # Eq. 3.4.8 def _decl_m(b, t): sum_m = 0 for i in range(len(self.block.all_time) - (n_steps - 1 - t)): sum_m += b.mf_history[n_steps - 1 - t + i] * time_step if sum_m > Z + self.block.mass_flow[t] * time_step: return i self.logger.warning('A proper value for m could not be calculated') return i self.block.m = Param(self.TIME, rule=_decl_m) # Define Y ##################################################################################################### # Eq. 3.4.9 self.block.Y = Var(lines, self.TIME) def _y(b, t, l): return b.Y[l, t] == sum( b.mf_history[i] * b.temperatures[l, i] * time_step for i in range(n_steps - 1 - t + b.n[t] + 1, n_steps - 1 - t + b.m[t])) self.block.def_Y = Constraint(self.TIME, lines, rule=_y) # Define S ##################################################################################################### # Eq 3.4.10 and 3.4.11 def _s(b, t): if b.m[t] > b.n[t]: return sum(b.mf_history[i] * time_step for i in range(n_steps - 1 - t, n_steps - 1 - t + b.m[t])) else: return b.R[t] self.block.S = Param(self.TIME, rule=_s) # Define outgoing temperature, without wall capacity and heat losses ########################################### # Eq. 3.4.12 def _def_temp_out_nhc(b, t, l): if b.mass_flow[t] == 0: return Constraint.Skip else: return b.temperature_out_nhc[l, t] == ( (b.R[t] - Z) * b.temperatures[ l, n_steps - 1 - t + b.n[t]] + b.Y[l, t] + ( b.mass_flow[t] * time_step - b.S[t] + Z) * b.temperatures[l, n_steps - 1 - t + b.m[t]]) \ / b.mass_flow[t] / time_step self.block.def_temp_out_nhc = Constraint(self.TIME, lines, rule=_def_temp_out_nhc) # Pipe wall heat capacity ###################################################################################### # Eq. 3.4.20 self.block.K = 1 / self.Rs[self.params['diameter'].v()] # Eq. 3.4.14 self.block.wall_temp = Var(lines, self.TIME) def _decl_temp_out_nhl(b, t, l): if t == 0: return Constraint.Skip elif b.mass_flow[t] == 0: return Constraint.Skip else: return b.temperature_out_nhl[l, t] == ( b.temperature_out_nhc[l, t] * b.mass_flow[t] * self.cp * time_step + C * b.wall_temp[l, t - 1]) / \ (C + b.mass_flow[t] * self.cp * time_step) def _temp_wall(b, t, l): if b.mass_flow[t] == 0: if t == 0: return Constraint.Skip else: return b.wall_temp[l, t] == Tg[t] + ( b.wall_temp[l, t - 1] - Tg[t]) * \ np.exp(-b.K * time_step / (surface * self.rho * self.cp + C / self.length)) else: return b.wall_temp[l, t] == b.temperature_out_nhl[l, t] # self.block.temp_wall = Constraint(self.TIME, lines, rule=_temp_wall) # Eq. 3.4.15 def _init_temp_wall(b, l): return b.wall_temp[l, 0] == self.params['wall_temperature_' + l].v() self.block.init_temp_wall = Constraint(lines, rule=_init_temp_wall) # def _decl_temp_out_nhl(b, t, l): # if t == 0: # return b.temperature_out_nhl[t, l] == (b.temperature_out_nhc[t, l] * (b.mass_flow[t] # * self.cp * time_step - C/2) # + C * b.wall_temp[t, l]) / \ # (C/2 + b.mass_flow[t] * self.cp * time_step) # else: # return b.temperature_out_nhl[t, l] == (b.temperature_out_nhc[t, l] * (b.mass_flow[t] # * self.cp * time_step - C/2) # + C * b.wall_temp[t-1, l]) / \ # (C/2 + b.mass_flow[t] * self.cp * time_step) self.block.decl_temp_out_nhl = Constraint(self.TIME, lines, rule=_decl_temp_out_nhl) # Eq. 3.4.18 # def _temp_wall(b, t, l): # if t == 0: # return Constraint.Skip # elif b.mass_flow[t] == 0: # return b.wall_temp[t, l] == Tg[t] + (b.wall_temp[t-1, l] - Tg[t]) * \ # np.exp(-b.K * time_step / # (surface * self.rho * self.cp + C/self.length)) # else: # return b.wall_temp[t, l] == b.wall_temp[t-1, l] + \ # ((b.temperature_out_nhc[t, l] - b.temperature_out_nhl[t, l]) * # b.mass_flow[t] * self.cp * time_step) / C self.block.temp_wall = Constraint(self.TIME, lines, rule=_temp_wall) # Heat losses ################################################################################################## # Eq. 3.4.24 def _tk(b, t): if b.mass_flow[t] == 0: return Constraint.Skip else: delta_time = time_step * ((b.R[t] - Z) * b.n[t] + sum( b.mf_history[n_steps - 1 - t + i] * time_step * i for i in range(b.n[t] + 1, b.m[t])) + (b.mass_flow[t] * time_step - b.S[ t] + Z) * b.m[t]) \ / b.mass_flow[t] / time_step return delta_time self.block.tk = Param(self.TIME, rule=_tk) # Eq. 3.4.27 def _temp_out(b, t, l): if b.mass_flow[t] == 0: if t == 0: return b.temperature_out[l, t] == self.params[ 'temperature_out_' + l].v() else: return b.temperature_out[l, t] == ( b.temperature_out[l, t - 1] - Tg[t]) * \ np.exp(-b.K * time_step / ( surface * self.rho * self.cp + C / self.length)) \ + Tg[t] else: return b.temperature_out[l, t] == Tg[t] + \ (b.temperature_out_nhl[l, t] - Tg[t]) * \ np.exp(-(b.K * b.tk[t]) / (surface * self.rho * self.cp)) self.block.def_temp_out = Constraint(self.TIME, lines, rule=_temp_out)
def unit_commitment_model(): model = ConcreteModel() # Define input files xlsx = pd.ExcelFile( f"{Path(__file__).parent.absolute()}/input/unit_commitment.xlsx", engine="openpyxl", ) system_demand = Helper.read_excel(xlsx, "SystemDemand") storage_systems = Helper.read_excel(xlsx, "StorageSystems") generators = Helper.read_excel(xlsx, "Generators") generator_step_size = Helper.read_excel(xlsx, "GeneratorStepSize") generator_step_cost = Helper.read_excel(xlsx, "GeneratorStepCost") pv_generation = Helper.read_excel(xlsx, "PVGeneration") # Define sets model.T = Set(ordered=True, initialize=system_demand.index) model.I = Set(ordered=True, initialize=generators.index) model.F = Set(ordered=True, initialize=generator_step_size.columns) model.S = Set(ordered=True, initialize=storage_systems.index) # Define parameters model.Pmax = Param(model.I, within=NonNegativeReals, mutable=True) model.Pmin = Param(model.I, within=NonNegativeReals, mutable=True) model.RU = Param(model.I, within=NonNegativeReals, mutable=True) model.RD = Param(model.I, within=NonNegativeReals, mutable=True) model.SUC = Param(model.I, within=NonNegativeReals, mutable=True) model.SDC = Param(model.I, within=NonNegativeReals, mutable=True) model.Pini = Param(model.I, within=NonNegativeReals, mutable=True) model.uini = Param(model.I, within=Binary, mutable=True) model.C = Param(model.I, model.F, within=NonNegativeReals, mutable=True) model.B = Param(model.I, model.F, within=NonNegativeReals, mutable=True) model.SystemDemand = Param(model.T, within=NonNegativeReals, mutable=True) model.Emissions = Param(model.I, within=NonNegativeReals, mutable=True) model.PV = Param(model.T, within=NonNegativeReals, mutable=True) model.ESS_Pmax = Param(model.S, within=NonNegativeReals, mutable=True) model.ESS_SOEmax = Param(model.S, within=NonNegativeReals, mutable=True) model.ESS_SOEini = Param(model.S, within=NonNegativeReals, mutable=True) model.ESS_Eff = Param(model.S, within=NonNegativeReals, mutable=True) # Give values to parameters of the generators for i in model.I: model.Pmin[i] = generators.loc[i, "Pmin"] model.Pmax[i] = generators.loc[i, "Pmax"] model.RU[i] = generators.loc[i, "RU"] model.RD[i] = generators.loc[i, "RD"] model.SUC[i] = generators.loc[i, "SUC"] model.SDC[i] = generators.loc[i, "SDC"] model.Pini[i] = generators.loc[i, "Pini"] model.uini[i] = generators.loc[i, "uini"] model.Emissions[i] = generators.loc[i, "Emissions"] for f in model.F: model.B[i, f] = generator_step_size.loc[i, f] model.C[i, f] = generator_step_cost.loc[i, f] # Add system demand and PV generation for t in model.T: model.SystemDemand[t] = system_demand.loc[t, "SystemDemand"] model.PV[t] = pv_generation.loc[t, "PVGeneration"] # Give values to ESS parameters for s in model.S: model.ESS_Pmax[s] = storage_systems.loc[s, "Power"] model.ESS_SOEmax[s] = storage_systems.loc[s, "Energy"] model.ESS_SOEini[s] = storage_systems.loc[s, "SOEini"] model.ESS_Eff[s] = storage_systems.loc[s, "Eff"] # Define decision variables model.P = Var(model.I, model.T, within=NonNegativeReals) model.Pres = Var(model.T, within=NonNegativeReals) model.b = Var(model.I, model.F, model.T, within=NonNegativeReals) model.u = Var(model.I, model.T, within=Binary) model.CSU = Var(model.I, model.T, within=NonNegativeReals) model.CSD = Var(model.I, model.T, within=NonNegativeReals) model.SOE = Var(model.S, model.T, within=NonNegativeReals) model.Pch = Var(model.S, model.T, within=NonNegativeReals) model.Pdis = Var(model.S, model.T, within=NonNegativeReals) model.u_ess = Var(model.S, model.T, within=Binary) # -------------------------------------- # Define the objective functions # -------------------------------------- def cost_objective(model): return sum( sum( sum(model.C[i, f] * model.b[i, f, t] for f in model.F) + model.CSU[i, t] + model.CSD[i, t] for i in model.I) for t in model.T) def emissions_objective(model): return sum( sum(model.P[i, t] * model.Emissions[i] for i in model.I) for t in model.T) def unmet_objective(model): return sum(model.Pres[t] for t in model.T) # -------------------------------------- # Define the regular constraints # -------------------------------------- def power_decomposition_rule1(model, i, t): return model.P[i, t] == sum(model.b[i, f, t] for f in model.F) def power_decomposition_rule2(model, i, f, t): return model.b[i, f, t] <= model.B[i, f] def power_min_rule(model, i, t): return model.P[i, t] >= model.Pmin[i] * model.u[i, t] def power_max_rule(model, i, t): return model.P[i, t] <= model.Pmax[i] * model.u[i, t] def ramp_up_rule(model, i, t): if model.T.ord(t) == 1: return model.P[i, t] - model.Pini[i] <= 60 * model.RU[i] if model.T.ord(t) > 1: return model.P[i, t] - model.P[i, model.T.prev(t)] <= 60 * model.RU[i] def ramp_down_rule(model, i, t): if model.T.ord(t) == 1: return (model.Pini[i] - model.P[i, t]) <= 60 * model.RD[i] if model.T.ord(t) > 1: return (model.P[i, model.T.prev(t)] - model.P[i, t]) <= 60 * model.RD[i] def start_up_cost(model, i, t): if model.T.ord(t) == 1: return model.CSU[i, t] >= model.SUC[i] * (model.u[i, t] - model.uini[i]) if model.T.ord(t) > 1: return model.CSU[i, t] >= model.SUC[i] * ( model.u[i, t] - model.u[i, model.T.prev(t)]) def shut_down_cost(model, i, t): if model.T.ord(t) == 1: return model.CSD[i, t] >= model.SDC[i] * (model.uini[i] - model.u[i, t]) if model.T.ord(t) > 1: return model.CSD[i, t] >= model.SDC[i] * ( model.u[i, model.T.prev(t)] - model.u[i, t]) def ESS_SOEupdate(model, s, t): if model.T.ord(t) == 1: return (model.SOE[s, t] == model.ESS_SOEini[s] + model.ESS_Eff[s] * model.Pch[s, t] - model.Pdis[s, t] / model.ESS_Eff[s]) if model.T.ord(t) > 1: return (model.SOE[s, t] == model.SOE[s, model.T.prev(t)] + model.ESS_Eff[s] * model.Pch[s, t] - model.Pdis[s, t] / model.ESS_Eff[s]) def ESS_SOElimit(model, s, t): return model.SOE[s, t] <= model.ESS_SOEmax[s] def ESS_Charging(model, s, t): return model.Pch[s, t] <= model.ESS_Pmax[s] * model.u_ess[s, t] def ESS_Discharging(model, s, t): return model.Pdis[s, t] <= model.ESS_Pmax[s] * (1 - model.u_ess[s, t]) def Balance(model, t): return model.PV[t] + sum(model.P[i, t] for i in model.I) + sum( model.Pdis[s, t] for s in model.S) == model.SystemDemand[t] - model.Pres[t] + sum( model.Pch[s, t] for s in model.S) def Pres_max(model, t): return model.Pres[t] <= 0.1 * model.SystemDemand[t] # -------------------------------------- # Add components to the model # -------------------------------------- # Add the constraints to the model model.power_decomposition_rule1 = Constraint( model.I, model.T, rule=power_decomposition_rule1) model.power_decomposition_rule2 = Constraint( model.I, model.F, model.T, rule=power_decomposition_rule2) model.power_min_rule = Constraint(model.I, model.T, rule=power_min_rule) model.power_max_rule = Constraint(model.I, model.T, rule=power_max_rule) model.start_up_cost = Constraint(model.I, model.T, rule=start_up_cost) model.shut_down_cost = Constraint(model.I, model.T, rule=shut_down_cost) model.ConSOEUpdate = Constraint(model.S, model.T, rule=ESS_SOEupdate) model.ConCharging = Constraint(model.S, model.T, rule=ESS_Charging) model.ConDischarging = Constraint(model.S, model.T, rule=ESS_Discharging) model.ConSOElimit = Constraint(model.S, model.T, rule=ESS_SOElimit) model.ConGenUp = Constraint(model.I, model.T, rule=ramp_up_rule) model.ConGenDown = Constraint(model.I, model.T, rule=ramp_down_rule) model.ConBalance = Constraint(model.T, rule=Balance) model.Pres_max = Constraint(model.T, rule=Pres_max) # Add the objective functions to the model using ObjectiveList(). Note # that the first index is 1 instead of 0! model.obj_list = ObjectiveList() model.obj_list.add(expr=cost_objective(model), sense=minimize) model.obj_list.add(expr=emissions_objective(model), sense=minimize) model.obj_list.add(expr=unmet_objective(model), sense=minimize) # By default deactivate all the objective functions for o in range(len(model.obj_list)): model.obj_list[o + 1].deactivate() return model
def __init__(self, nfe_t, ncp_t, **kwargs): ConcreteModel.__init__(self) steady = kwargs.pop('steady', False) _t = kwargs.pop('_t', 1.0) Ntray = kwargs.pop('Ntray', 42) # -------------------------------------------------------------------------------------------------------------- # Orthogonal Collocation Parameters section # Radau self._alp_gauB_t = 1 self._bet_gauB_t = 0 if steady: print("[I] " + str(self.__class__.__name__) + " NFE and NCP Overriden - Steady state mode") self.nfe_t = 1 self.ncp_t = 1 else: self.nfe_t = nfe_t self.ncp_t = ncp_t self.tau_t = collptsgen(self.ncp_t, self._alp_gauB_t, self._bet_gauB_t) # start at zero self.tau_i_t = {0: 0.} # create a list for ii in range(1, self.ncp_t + 1): self.tau_i_t[ii] = self.tau_t[ii - 1] # ======= SETS ======= # # For finite element = 1 .. NFE # This has to be > 0 self.fe_t = Set(initialize=[ii for ii in range(1, self.nfe_t + 1)]) # collocation points # collocation points for differential variables self.cp_t = Set(initialize=[ii for ii in range(0, self.ncp_t + 1)]) # collocation points for algebraic variables self.cp_ta = Set(within=self.cp_t, initialize=[ii for ii in range(1, self.ncp_t + 1)]) # create collocation param self.taucp_t = Param(self.cp_t, initialize=self.tau_i_t) self.ldot_t = Param(self.cp_t, self.cp_t, initialize= (lambda m, j, k: lgrdot(k, m.taucp_t[j], self.ncp_t, self._alp_gauB_t, self._bet_gauB_t))) #: watch out for this! self.l1_t = Param(self.cp_t, initialize= (lambda m, j: lgr(j, 1, self.ncp_t, self._alp_gauB_t, self._bet_gauB_t))) # -------------------------------------------------------------------------------------------------------------- # Model parameters self.Ntray = Ntray self.tray = Set(initialize=[i for i in range(1, Ntray + 1)]) self.feed = Param(self.tray, initialize=lambda m, t: 57.5294 if t == 21 else 0.0, mutable=True) self.xf = Param(initialize=0.32, mutable=True) # feed mole fraction self.hf = Param(initialize=9081.3) # feed enthalpy self.hlm0 = Param(initialize=2.6786e-04) self.hlma = Param(initialize=-0.14779) self.hlmb = Param(initialize=97.4289) self.hlmc = Param(initialize=-2.1045e04) self.hln0 = Param(initialize=4.0449e-04) self.hlna = Param(initialize=-0.1435) self.hlnb = Param(initialize=121.7981) self.hlnc = Param(initialize=-3.0718e04) self.r = Param(initialize=8.3147) self.a = Param(initialize=6.09648) self.b = Param(initialize=1.28862) self.c1 = Param(initialize=1.016) self.d = Param(initialize=15.6875) self.l = Param(initialize=13.4721) self.f = Param(initialize=2.615) self.gm = Param(initialize=0.557) self.Tkm = Param(initialize=512.6) self.Pkm = Param(initialize=8.096e06) self.gn = Param(initialize=0.612) self.Tkn = Param(initialize=536.7) self.Pkn = Param(initialize=5.166e06) self.CapAm = Param(initialize=23.48) self.CapBm = Param(initialize=3626.6) self.CapCm = Param(initialize=-34.29) self.CapAn = Param(initialize=22.437) self.CapBn = Param(initialize=3166.64) self.CapCn = Param(initialize=-80.15) self.pstrip = Param(initialize=250) self.prect = Param(initialize=190) def _p_init(m, t): ptray = 9.39e04 if t <= 20: return _p_init(m, 21) + m.pstrip * (21 - t) elif 20 < t < m.Ntray: return ptray + m.prect * (m.Ntray - t) elif t == m.Ntray: return 9.39e04 self.p = Param(self.tray, initialize=_p_init) self.T29_des = Param(initialize=343.15) self.T15_des = Param(initialize=361.15) self.Dset = Param(initialize=1.83728) self.Qcset = Param(initialize=1.618890) self.Qrset = Param(initialize=1.786050) # self.Recset = Param() self.alpha_T29 = Param(initialize=1) self.alpha_T15 = Param(initialize=1) self.alpha_D = Param(initialize=1) self.alpha_Qc = Param(initialize=1) self.alpha_Qr = Param(initialize=1) self.alpha_Rec = Param(initialize=1) def _alpha_init(m, i): if i <= 21: return 0.62 else: return 0.35 self.alpha = Param(self.tray, initialize=lambda m, t: 0.62 if t <= 21 else 0.35) # -------------------------------------------------------------------------------------------------------------- #: First define differential state variables (state: x, ic-Param: x_ic, derivative-Var:dx_dt #: States (differential) section zero_tray = dict.fromkeys(self.tray) zero3 = dict.fromkeys(self.fe_t * self.cp_t * self.tray) for key in zero3.keys(): zero3[key] = 0.0 def __m_init(m, i, j, t): if t < m.Ntray: return 4000. elif t == 1: return 104340. elif t == m.Ntray: return 5000. #: Liquid hold-up self.M = Var(self.fe_t, self.cp_t, self.tray, initialize=__m_init) #: Mole-fraction self.x = Var(self.fe_t, self.cp_t, self.tray, initialize=lambda m, i, j, t: 0.999 * t / m.Ntray) #: Initial state-Param self.M_ic = zero_tray if steady else Param(self.tray, initialize=0.0, mutable=True) self.x_ic = zero_tray if steady else Param(self.tray, initialize=0.0, mutable=True) #: Derivative-var self.dM_dt = zero3 if steady else Var(self.fe_t, self.cp_t, self.tray, initialize=0.0) self.dx_dt = zero3 if steady else Var(self.fe_t, self.cp_t, self.tray, initialize=0.0) # -------------------------------------------------------------------------------------------------------------- # States (algebraic) section # Tray temperature self.T = Var(self.fe_t, self.cp_ta, self.tray, initialize=lambda m, i, j, t: ((370.781 - 335.753) / m.Ntray) * t + 370.781) self.Tdot = Var(self.fe_t, self.cp_ta, self.tray, initialize=1e-05) #: Not really a der_var # saturation pressures self.pm = Var(self.fe_t, self.cp_ta, self.tray, initialize=1e4) self.pn = Var(self.fe_t, self.cp_ta, self.tray, initialize=1e4) # Vapor mole flowrate self.V = Var(self.fe_t, self.cp_ta, self.tray, initialize=44.0) def _l_init(m, i, j, t): if 2 <= t <= 21: return 83. elif 22 <= t <= 42: return 23 elif t == 1: return 40 # Liquid mole flowrate self.L = Var(self.fe_t, self.cp_ta, self.tray, initialize=_l_init) # Vapor mole frac & diff var self.y = Var(self.fe_t, self.cp_ta, self.tray, initialize=lambda m, i, j, t: ((0.99 - 0.005) / m.Ntray) * t + 0.005) # Liquid enthalpy # enthalpy self.hl = Var(self.fe_t, self.cp_ta, self.tray, initialize=10000.) # Liquid enthalpy # enthalpy self.hv = Var(self.fe_t, self.cp_ta, self.tray, initialize=5e+04) # Re-boiler & condenser heat self.Qc = Var(self.fe_t, self.cp_ta, initialize=1.6e06) self.D = Var(self.fe_t, self.cp_ta, initialize=18.33) # vol holdups self.Vm = Var(self.fe_t, self.cp_ta, self.tray, initialize=6e-05) self.Mv = Var(self.fe_t, self.cp_ta, self.tray, initialize=lambda m, i, j, t: 0.23 if 1 < t < m.Ntray else 0.0) self.Mv1 = Var(self.fe_t, self.cp_ta, initialize=8.57) self.Mvn = Var(self.fe_t, self.cp_ta, initialize=0.203) hi_t = dict.fromkeys(self.fe_t) for key in hi_t.keys(): hi_t[key] = 1.0 if steady else _t/self.nfe_t self.hi_t = hi_t if steady else Param(self.fe_t, initialize=hi_t) # -------------------------------------------------------------------------------------------------------------- #: Controls self.u1 = Param(self.fe_t, initialize=7.72700925775773761472464684629813E-01, mutable=True) #: Dummy self.u2 = Param(self.fe_t, initialize=1.78604740940007800236344337463379E+06, mutable=True) #: Dummy self.Rec = Var(self.fe_t, initialize=7.72700925775773761472464684629813E-01) self.Qr = Var(self.fe_t, initialize=1.78604740940007800236344337463379E+06) # -------------------------------------------------------------------------------------------------------------- #: Constraints for the differential states #: Then the ode-Con:de_x, collocation-Con:dvar_t_x, noisy-Expr: noisy_x, cp-Constraint: cp_x, initial-Con: x_icc #: Differential equations self.de_M = Constraint(self.fe_t, self.cp_ta, self.tray, rule=m_ode) self.de_x = Constraint(self.fe_t, self.cp_ta, self.tray, rule=x_ode) #: Collocation equations self.dvar_t_M = None if steady else Constraint(self.fe_t, self.cp_ta, self.tray, rule=M_COLL) self.dvar_t_x = None if steady else Constraint(self.fe_t, self.cp_ta, self.tray, rule=x_coll) #: Continuation equations (redundancy here) if self.nfe_t > 1: #: Noisy expressions self.noisy_M = None if steady else Expression(self.fe_t, self.tray, rule=M_CONT) self.noisy_x = None if steady else Expression(self.fe_t, self.tray, rule=x_cont) #: Continuation equations self.cp_M = None if steady else \ Constraint(self.fe_t, self.tray, rule=lambda m, i, t: self.noisy_M[i, t] == 0.0 if i < self.nfe_t else Constraint.Skip) self.cp_x = None if steady else \ Constraint(self.fe_t, self.tray, rule=lambda m, i, t: self.noisy_x[i, t] == 0.0 if i < self.nfe_t else Constraint.Skip) #: Initial condition-Constraints self.M_icc = None if steady else Constraint(self.tray, rule=acm) self.x_icc = None if steady else Constraint(self.tray, rule=acx) # -------------------------------------------------------------------------------------------------------------- #: Constraint section (algebraic equations) self.hrc = Constraint(self.fe_t, self.cp_ta, rule=hrc) self.gh = Constraint(self.fe_t, self.cp_ta, self.tray, rule=gh) self.ghb = Constraint(self.fe_t, self.cp_ta, rule=ghb) self.ghc = Constraint(self.fe_t, self.cp_ta, rule=ghc) self.hkl = Constraint(self.fe_t, self.cp_ta, self.tray, rule=hkl) self.hkv = Constraint(self.fe_t, self.cp_ta, self.tray, rule=hkv) self.lpself = Constraint(self.fe_t, self.cp_ta, self.tray, rule=lpm) self.lpn = Constraint(self.fe_t, self.cp_ta, self.tray, rule=lpn) self.dp = Constraint(self.fe_t, self.cp_ta, self.tray, rule=dp) self.lTdot = Constraint(self.fe_t, self.cp_ta, self.tray, rule=lTdot) self.gy0 = Constraint(self.fe_t, self.cp_ta, rule=gy0) self.gy = Constraint(self.fe_t, self.cp_ta, self.tray, rule=gy) self.dMV = Constraint(self.fe_t, self.cp_ta, self.tray, rule=dMV) self.dMv1 = Constraint(self.fe_t, self.cp_ta, rule=dMv1) self.dMvn = Constraint(self.fe_t, self.cp_ta, rule=dMvn) self.hyd = Constraint(self.fe_t, self.cp_ta, self.tray, rule=hyd) self.hyd1 = Constraint(self.fe_t, self.cp_ta, rule=hyd1) self.hydN = Constraint(self.fe_t, self.cp_ta, rule=hydN) self.dvself = Constraint(self.fe_t, self.cp_ta, self.tray, rule=dvm) # -------------------------------------------------------------------------------------------------------------- #: Control constraint self.u1_e = Expression(self.fe_t, rule=lambda m, i: self.Rec[i]) self.u2_e = Expression(self.fe_t, rule=lambda m, i: self.Qr[i]) self.u1_c = Constraint(self.fe_t, rule=lambda m, i: self.u1[i] == self.u1_e[i]) self.u2_c = Constraint(self.fe_t, rule=lambda m, i: self.u2[i] == self.u2_e[i]) # -------------------------------------------------------------------------------------------------------------- #: Suffixes self.dual = Suffix(direction=Suffix.IMPORT_EXPORT) self.ipopt_zL_out = Suffix(direction=Suffix.IMPORT) self.ipopt_zU_out = Suffix(direction=Suffix.IMPORT) self.ipopt_zL_in = Suffix(direction=Suffix.EXPORT) self.ipopt_zU_in = Suffix(direction=Suffix.EXPORT)
def make_separation_problem(model_data, config): """ Swap out uncertain param Param objects for Vars Add uncertainty set constraints and separation objectives """ separation_model = model_data.original.clone() separation_model.del_component("coefficient_matching_constraints") separation_model.del_component("coefficient_matching_constraints_index") uncertain_params = separation_model.util.uncertain_params separation_model.util.uncertain_param_vars = param_vars = Var( range(len(uncertain_params))) map_new_constraint_list_to_original_con = ComponentMap() if config.objective_focus is ObjectiveType.worst_case: separation_model.util.zeta = Param(initialize=0, mutable=True) constr = Constraint(expr=separation_model.first_stage_objective + separation_model.second_stage_objective - separation_model.util.zeta <= 0) separation_model.add_component("epigraph_constr", constr) substitution_map = {} #Separation problem initialized to nominal uncertain parameter values for idx, var in enumerate(list(param_vars.values())): param = uncertain_params[idx] var.set_value(param.value, skip_validation=True) substitution_map[id(param)] = var separation_model.util.new_constraints = constraints = ConstraintList() uncertain_param_set = ComponentSet(uncertain_params) for c in separation_model.component_data_objects(Constraint): if any(v in uncertain_param_set for v in identify_mutable_parameters(c.expr)): if c.equality: constraints.add( replace_expressions(expr=c.lower, substitution_map=substitution_map) == replace_expressions(expr=c.body, substitution_map=substitution_map)) elif c.lower is not None: constraints.add( replace_expressions(expr=c.lower, substitution_map=substitution_map) <= replace_expressions(expr=c.body, substitution_map=substitution_map)) elif c.upper is not None: constraints.add( replace_expressions(expr=c.upper, substitution_map=substitution_map) >= replace_expressions(expr=c.body, substitution_map=substitution_map)) else: raise ValueError( "Unable to parse constraint for building the separation problem." ) c.deactivate() map_new_constraint_list_to_original_con[constraints[ constraints.index_set().last()]] = c separation_model.util.map_new_constraint_list_to_original_con = map_new_constraint_list_to_original_con # === Add objectives first so that the uncertainty set # Constraints do not get picked up into the set # of performance constraints which become objectives make_separation_objective_functions(separation_model, config) add_uncertainty_set_constraints(separation_model, config) # === Deactivate h(x,q) == 0 constraints for c in separation_model.util.h_x_q_constraints: c.deactivate() return separation_model
def create_nmpc(self, **kwargs): kwargs.pop("newnfe", self.nfe_tnmpc) kwargs.pop("newncp", self.ncp_tnmpc) self.journalist('W', self._iteration_count, "Initializing NMPC", "With {:d} fe and {:d} cp".format(self.nfe_tnmpc, self.ncp_tnmpc)) _tnmpc = self.hi_t * self.nfe_tnmpc self.olnmpc = self.d_mod(self.nfe_tnmpc, self.ncp_tnmpc, _t=_tnmpc) self.olnmpc.name = "olnmpc (Open-Loop NMPC)" self.olnmpc.create_bounds() for u in self.u: cv = getattr(self.olnmpc, u) #: Get the param c_val = [value(cv[i]) for i in cv.keys()] #: Current value self.olnmpc.del_component(cv) #: Delete the param self.olnmpc.add_component(u, Var(self.olnmpc.fe_t, initialize=lambda m, i: c_val[i-1])) self.olnmpc.equalize_u(direction="r_to_u") cc = getattr(self.olnmpc, u + "_c") #: Get the constraint ce = getattr(self.olnmpc, u + "_e") #: Get the expression cv = getattr(self.olnmpc, u) #: Get the new variable for k in cv.keys(): cv[k].setlb(self.u_bounds[u][0]) cv[k].setub(self.u_bounds[u][1]) cc.clear() cc.rule = lambda m, i: cv[i] == ce[i] cc.reconstruct() #: Dictionary of the states for a particular time point i self.xmpc_l = {} #: Dictionary of the position for a state in the dictionary self.xmpc_key = {} #: self.xmpc_l[0] = [] #: First build the name dictionary k = 0 for x in self.states: n_s = getattr(self.olnmpc, x) #: State for j in self.state_vars[x]: self.xmpc_l[0].append(n_s[(0, self.ncp_tnmpc) + j]) self.xmpc_key[(x, j)] = k k += 1 #: Iterate over the rest for t in range(1, self.nfe_tnmpc): self.xmpc_l[t] = [] for x in self.states: n_s = getattr(self.olnmpc, x) #: State for j in self.state_vars[x]: self.xmpc_l[t].append(n_s[(t, self.ncp_tnmpc) + j]) #: A set with the length of flattened states self.olnmpc.xmpcS_nmpc = Set(initialize=[i for i in range(0, len(self.xmpc_l[0]))]) #: Create set of noisy_states self.olnmpc.xmpc_ref_nmpc = Param(self.olnmpc.xmpcS_nmpc, initialize=0.0, mutable=True) #: Ref-state self.olnmpc.Q_nmpc = Param(self.olnmpc.xmpcS_nmpc, initialize=1, mutable=True) #: Control-weight # (diagonal Matrices) self.olnmpc.Q_w_nmpc = Param(self.olnmpc.fe_t, initialize=1e-04, mutable=True) self.olnmpc.R_w_nmpc = Param(self.olnmpc.fe_t, initialize=1e+02, mutable=True) #: Build the xT*Q*x part self.olnmpc.xQ_expr_nmpc = Expression(expr=sum( sum(self.olnmpc.Q_w_nmpc[fe] * self.olnmpc.Q_nmpc[k] * (self.xmpc_l[fe][k] - self.olnmpc.xmpc_ref_nmpc[k])**2 for k in self.olnmpc.xmpcS_nmpc) for fe in range(0, self.nfe_tnmpc))) #: Build the control list self.umpc_l = {} for t in range(0, self.nfe_tnmpc): self.umpc_l[t] = [] for u in self.u: uvar = getattr(self.olnmpc, u) self.umpc_l[t].append(uvar[t]) #: Create set of u self.olnmpc.umpcS_nmpc = Set(initialize=[i for i in range(0, len(self.umpc_l[0]))]) #: ref u self.olnmpc.umpc_ref_nmpc = Param(self.olnmpc.umpcS_nmpc, initialize=0.0, mutable=True) self.olnmpc.R_nmpc = Param(self.olnmpc.umpcS_nmpc, initialize=1, mutable=True) #: Control-weight #: Build the uT * R * u expression self.olnmpc.xR_expr_nmpc = Expression(expr=sum( sum(self.olnmpc.R_w_nmpc[fe] * self.olnmpc.R_nmpc[k] * (self.umpc_l[fe][k] - self.olnmpc.umpc_ref_nmpc[k]) ** 2 for k in self.olnmpc.umpcS_nmpc) for fe in range(0, self.nfe_tnmpc))) self.olnmpc.objfun_nmpc = Objective(expr=self.olnmpc.xQ_expr_nmpc + self.olnmpc.xR_expr_nmpc)