def create_model(): """ defining the model """ model = po.ConcreteModel() model.t = pod.ContinuousSet(bounds=(0, 1)) model.tau = po.Var() model.temp = po.Var() model.ca = po.Var(model.t, bounds=(0, 50)) model.cb = po.Var(model.t, bounds=(0, 50)) model.dca_dt = pod.DerivativeVar(model.ca, wrt=model.t) model.dcb_dt = pod.DerivativeVar(model.cb, wrt=model.t) model.theta_0 = po.Var() # model parameters model.theta_1 = po.Var() model.alpha_a = po.Var() model.alpha_b = po.Var() model.nu = po.Var() def _material_balance_a(m, t): k = po.exp(m.theta_0 + m.theta_1 * (m.temp - 273.15) / m.temp) return m.scipy_model[t] / m.tau == - k * (m.ca[t] ** model.alpha_a) * ( model.cb[t] ** model.alpha_b) model.material_balance_a = po.Constraint(model.t, rule=_material_balance_a) def _material_balance_b(m, t): k = po.exp(m.theta_0 + m.theta_1 * (m.temp - 273.15) / m.temp) return m.dcb_dt[t] / m.tau == m.nu * k * (m.ca[t] ** model.alpha_a) * ( model.cb[t] ** model.alpha_b) model.material_balance_b = po.Constraint(model.t, rule=_material_balance_b) return model
def car_example(): """This is to test problems where a differential variable doesn't appear in a constraint this is based on a Pyomo example here: https://github.com/Pyomo/pyomo/blob/main/examples/dae/car_example.py""" m = pyo.ConcreteModel() m.R = pyo.Param(initialize=0.001) # Friction factor m.L = pyo.Param(initialize=100.0) # Final position m.tau = pyodae.ContinuousSet(bounds=(0, 1)) # Unscaled time m.time = pyo.Var(m.tau) # Scaled time m.tf = pyo.Var() m.x = pyo.Var(m.tau, bounds=(0, m.L + 50)) m.v = pyo.Var(m.tau, bounds=(0, None)) m.a = pyo.Var(m.tau, bounds=(-3.0, 1.0), initialize=0) m.dtime = pyodae.DerivativeVar(m.time) m.dx = pyodae.DerivativeVar(m.x) m.dv = pyodae.DerivativeVar(m.v) m.obj = pyo.Objective(expr=m.tf) def _ode1(m, i): if i == 0: return pyo.Constraint.Skip return m.dx[i] == m.tf * m.v[i] m.ode1 = pyo.Constraint(m.tau, rule=_ode1) def _ode2(m, i): if i == 0: return pyo.Constraint.Skip return m.dv[i] == m.tf * (m.a[i] - m.R * m.v[i]**2) m.ode2 = pyo.Constraint(m.tau, rule=_ode2) def _ode3(m, i): if i == 0: return pyo.Constraint.Skip return m.dtime[i] == m.tf m.ode3 = pyo.Constraint(m.tau, rule=_ode3) def _init(m): yield m.x[0] == 0 #yield m.x[1] == m.L yield m.v[0] == 0 yield m.v[1] == 0 yield m.time[0] == 0 m.initcon = pyo.ConstraintList(rule=_init) discretizer = pyo.TransformationFactory('dae.finite_difference') discretizer.apply_to(m, nfe=1, scheme='BACKWARD') return m
def create_model(spt): """ defining the model """ norm_spt = spt / max(spt) model = po.ConcreteModel() model.t = pod.ContinuousSet(bounds=(0, 1), initialize=norm_spt) model.tau = po.Var() model.temp = po.Var(model.t, bounds=(200, 400)) # reaction temperature in K model.ca = po.Var(model.t, bounds=(0, 50)) model.cb = po.Var(model.t, bounds=(0, 50)) model.dca_dt = pod.DerivativeVar(model.ca, wrt=model.t) model.dcb_dt = pod.DerivativeVar(model.cb, wrt=model.t) model.theta_0 = po.Var() # model parameters model.theta_1 = po.Var() model.alpha_a = po.Var() model.alpha_b = po.Var() model.nu = po.Var() model.q_in = po.Var(model.t, bounds=(0, None)) # volumetric flow rate into the reactor in L/min model.ca_in = po.Var(model.t, bounds=(0, None)) # molar concentration of A in q_in in mol/L model.cb_in = po.Var(model.t, bounds=(0, None)) # molar concentration of B in q_in in mol/L model.v = po.Var(model.t, bounds=(0, None)) # volume of reaction mixture in L model.dvdt = pod.DerivativeVar(model.v, wrt=model.t) model.tvc = po.Suffix(direction=po.Suffix.LOCAL) def _material_balance_a(m, t): k = po.exp(m.theta_0 + m.theta_1 * (m.temp[t] - 273.15) / m.temp[t]) return m.dca_dt[t] / m.tau == m.q_in[t] / m.v[t] * (m.ca_in[t] - m.ca[t]) - k * (m.ca[t] ** model.alpha_a) * ( model.cb[t] ** model.alpha_b) model.material_balance_a = po.Constraint(model.t, rule=_material_balance_a) def _material_balance_b(m, t): k = po.exp(m.theta_0 + m.theta_1 * (m.temp[t] - 273.15) / m.temp[t]) return m.dcb_dt[t] / m.tau == m.q_in[t] / m.v[t] * (m.cb_in[t] - m.cb[t]) + m.nu * k * (m.ca[t] ** model.alpha_a) * ( model.cb[t] ** model.alpha_b) model.material_balance_b = po.Constraint(model.t, rule=_material_balance_b) def _volume_balance(m, t): return m.dvdt[t] == m.q_in[t] model.volume_balance = po.Constraint(model.t, rule=_volume_balance) return model
def make_model(horizon=10.0): m = pyo.ConcreteModel() m.comp = pyo.Set(initialize=["A", "B"]) m.time = dae.ContinuousSet(initialize=[0, horizon]) time = m.time comp = m.comp m.stoich = pyo.Param(m.comp, initialize={"A": -1, "B": 1}, mutable=True) m.k_rxn = pyo.Param(initialize=1.0, mutable=True) m.conc = pyo.Var(m.time, m.comp) m.dcdt = dae.DerivativeVar(m.conc, wrt=m.time) m.flow_in = pyo.Var(time) m.flow_out = pyo.Var(time) m.flow_eqn = pyo.Constraint(time, rule=_flow_eqn_rule) m.conc_in = pyo.Var(time, comp) m.conc_out = pyo.Var(time, comp) m.conc_out_eqn = pyo.Constraint(time, comp, rule=_conc_out_eqn_rule) m.rate_gen = pyo.Var(time, comp) m.rate_eqn = pyo.Constraint(time, comp, rule=_rate_eqn_rule) m.conc_diff_eqn = pyo.Constraint(time, comp, rule=_conc_diff_eqn_rule) return m
def rp_example3(): """ This example is done multiple ways to test a few common errors where the integrator and fully time-discretized problem differ, and alternative working formulations. Another way to formulate this problem is to fix the derivative. This doesn't work for the integrator because it loses the association between the differential variable and its derivative. Since for users, the result of this formulation may be unexpected, the PETSc utilities will raise an exception if derivatives are fixed to anything other than 0. """ m = pyo.ConcreteModel() m.time = pyodae.ContinuousSet(initialize=(0.0, 10.0)) m.x = pyo.Var(m.time) m.u = pyo.Var(m.time) m.dxdt = pyodae.DerivativeVar(m.x, wrt=m.time) def diff_eq_rule(m, t): return m.dxdt[t] == m.x[t]**2 - m.u[t] m.diff_eq = pyo.Constraint(m.time, rule=diff_eq_rule) discretizer = pyo.TransformationFactory('dae.finite_difference') discretizer.apply_to(m, nfe=1, scheme='BACKWARD') m.u[0].fix(1.0) m.dxdt[:].fix(2.0) return m
def make_dynamic_model(**disc_args): # Level control model m = pyo.ConcreteModel() m.time = dae.ContinuousSet(initialize=[0.0, 10.0]) m.height = pyo.Var(m.time, initialize=1.0) m.flow_in = pyo.Var(m.time, initialize=1.0) m.flow_out = pyo.Var(m.time, initialize=0.5) m.dhdt = dae.DerivativeVar(m.height, wrt=m.time, initialize=0.0) m.area = pyo.Param(initialize=1.0) m.flow_const = pyo.Param(initialize=0.5) def diff_eqn_rule(m, t): return m.area * m.dhdt[t] - (m.flow_in[t] - m.flow_out[t]) == 0 m.diff_eqn = pyo.Constraint(m.time, rule=diff_eqn_rule) def flow_out_rule(m, t): return m.flow_out[t] - (m.flow_const * pyo.sqrt(m.height[t])) == 0 m.flow_out_eqn = pyo.Constraint(m.time, rule=flow_out_rule) default_disc_args = { "wrt": m.time, "nfe": 5, "scheme": "BACKWARD", } default_disc_args.update(disc_args) discretizer = pyo.TransformationFactory("dae.finite_difference") discretizer.apply_to(m, **default_disc_args) return m
def rp_example(): """This example is done multiple ways to test a few common errors where the integrator and fully time-discretized problem differ and alternative working formulations. The PETSc utilities raise an exception when a differential variable is fixed. While this is okay for the fully time-discretized problem, the integrator will not correctly link a fixed differential variable (at non-initial time points) with a time derivative. """ m = pyo.ConcreteModel() m.time = pyodae.ContinuousSet(initialize=(0.0, 10.0)) m.x = pyo.Var(m.time) m.u = pyo.Var(m.time) m.dxdt = pyodae.DerivativeVar(m.x, wrt=m.time) def diff_eq_rule(m, t): return m.dxdt[t] == m.x[t]**2 - m.u[t] m.diff_eq = pyo.Constraint(m.time, rule=diff_eq_rule) discretizer = pyo.TransformationFactory('dae.finite_difference') discretizer.apply_to(m, nfe=1, scheme='BACKWARD') for t in m.time: m.x[t].fix(2.0 * t) m.u[0].fix(1.0) return m
def rp_example4(): """ This example is done multiple ways to test a few common errors where the integrator and fully time-discretized problem differ, and alternative working formulations. Rather than fixing the derivative, we can add a constraint to set the derivative. This should work as intended for both the fully time-discretized problem and integrator. """ m = pyo.ConcreteModel() m.time = pyodae.ContinuousSet(initialize=(0.0, 10.0)) m.x = pyo.Var(m.time, initialize=1) m.u = pyo.Var(m.time, initialize=1) m.dxdt = pyodae.DerivativeVar(m.x, wrt=m.time) def diff_eq1_rule(m, t): return m.dxdt[t] == m.x[t]**2 - m.u[t] m.diff_eq1 = pyo.Constraint(m.time, rule=diff_eq1_rule) def diff_eq2_rule(m, t): return m.dxdt[t] == 2.0 m.diff_eq2 = pyo.Constraint(m.time, rule=diff_eq2_rule) discretizer = pyo.TransformationFactory('dae.finite_difference') discretizer.apply_to(m, nfe=1, scheme='BACKWARD') m.u[0].fix(1.0) m.x[0].fix(0.0) m.diff_eq2[0].deactivate() return m
def create_pyomo_model(sampling_times): """ Creates a pyomo model. Return: model : the ConcreteModel instance. simulator : Pyomo.DAE's simulator object attached to the model. """ model = po.ConcreteModel() norm_spt = sampling_times / max(sampling_times) model.t = pod.ContinuousSet(bounds=(0, 1), initialize=norm_spt) model.tau = po.Var() model.ca = po.Var(model.t, bounds=(0, 50)) # set of concentrations in reaction mixture model.dca_dt = pod.DerivativeVar(model.ca, wrt=model.t) model.beta = po.Var() # model parameters def _material_balance(m, t): return m.dca_dt[t] / m.tau == -m.beta * m.ca[t] model.material_balance = po.Constraint(model.t, rule=_material_balance) return model
def create_model(spt): norm_spt = spt / np.max(spt) m = po.ConcreteModel() """ Sets """ m.i = po.Set(initialize=["A", "B", "C"]) m.j = po.Set(initialize=[1, 2]) """ Time Components """ m.t = pod.ContinuousSet(bounds=(0, 1), initialize=norm_spt) m.tau = po.Var(bounds=(0, None)) """ Concentrations """ m.c = po.Var(m.t, m.i, bounds=(0, None)) m.dcdt = pod.DerivativeVar(m.c, wrt=m.t) """ Experimental Variables """ m.f_in = po.Var(bounds=(0, 10)) """ Reaction Parameters """ s = { ("A", 1): -1, ("A", 2): 0, ("B", 1): 1, ("B", 2): -1, ("C", 1): 0, ("C", 2): 1, } m.s = po.Param(m.i, m.j, initialize=s) c_in = { "A": 1, "B": 0, "C": 0, } m.c_in = po.Param(m.i, initialize=c_in) """ Model Parameters """ m.k = po.Var(m.j, bounds=(0, None)) """ Reaction Rates """ m.r = po.Var(m.t, m.j) """ Model Equations """ def _bal(m, t, i): return m.dcdt[t, i] / m.tau == m.f_in * m.c_in[i] + sum(m.s[i, j] * m.r[t, j] for j in m.j) m.bal = po.Constraint(m.t, m.i, rule=_bal) def _r_def(m, t, j): if j == 1: return m.r[t, j] == m.k[j] * m.c[t, "A"] elif j == 2: return m.r[t, j] == m.k[j] * m.c[t, "B"] else: raise SyntaxError("Unrecognized reaction index, please check the model.") m.r_def = po.Constraint(m.t, m.j, rule=_r_def) return m
def create_model(spt): model = po.ConcreteModel() model.t = pod.ContinuousSet(bounds=(0, 1), initialize=spt) model.tau = po.Var(bounds=(0, None)) model.cA = po.Var(model.t, bounds=(0, None)) model.cB = po.Var(model.t, bounds=(0, None)) model.dcAdt = pod.DerivativeVar(model.cA, wrt=model.t) model.dcBdt = pod.DerivativeVar(model.cB, wrt=model.t) model.nu = po.Var(bounds=(0, None)) model.alpha = po.Var(bounds=(0, None)) model.beta = po.Var(bounds=(0, None)) model.T = po.Var(bounds=(0, None)) model.theta_10 = po.Var() model.theta_11 = po.Var() model.theta_20 = po.Var() model.theta_21 = po.Var() model.theta_30 = po.Var() model.theta_31 = po.Var() def _A_mol_bal(m, t): k1 = po.exp(m.theta_10 + m.theta_11 * (m.T - 273.15) / m.T) k2 = po.exp(m.theta_20 + m.theta_21 * (m.T - 273.15) / m.T) k3 = po.exp(m.theta_30 + m.theta_31 * (m.T - 273.15) / m.T) r = k1 * m.cA[t]**m.alpha / (k2 + k3 * m.cA[t]**m.beta) return m.dcAdt[t] == m.tau * -r model.A_mol_bal = po.Constraint(model.t, rule=_A_mol_bal) def _B_mol_bal(m, t): k1 = po.exp(m.theta_10 + m.theta_11 * (m.T - 273.15) / m.T) k2 = po.exp(m.theta_20 + m.theta_21 * (m.T - 273.15) / m.T) k3 = po.exp(m.theta_30 + m.theta_31 * (m.T - 273.15) / m.T) r = k1 * m.cA[t]**m.alpha / (k2 + k3 * m.cA[t]**m.beta) return m.dcBdt[t] == m.tau * m.nu * r model.B_mol_bal = po.Constraint(model.t, rule=_B_mol_bal) simulator = pod.Simulator(model, package="casadi") return model, simulator
def create_model_hgp(spt): m = po.ConcreteModel() tau = max(spt) norm_spt = spt / tau m.t = pod.ContinuousSet(bounds=(0, 1), initialize=norm_spt) # normalized time variable (unitless) m.tau = po.Var(bounds=(0, None)) # batch time in hours m.p = po.Var(m.t, bounds=(0, None)) # pressure in reservoir in MPa m.dpdt = pod.DerivativeVar(m.p, wrt=m.t) # rate of change of pressure per day m.v = po.Var(bounds=(0, 1)) # the unknown volume of the reservoir in trillion cubic metres m.T = po.Var(bounds=(0, None)) # the temperature in the reservoir, assumed isothermal m.q = po.Var(m.t, bounds=(0, None)) # gas flowrate taken out in examoles per day (10^{18} moles per day) m.p_vac = po.Var(m.t, bounds=(21.90, 22), initialize=21.95) # outlet pressure that drive gas extraction in MPa m.mu = po.Var(bounds=(0, None)) # dynamic viscosity of gas in MPa.day m.L = po.Var(bounds=(0, None)) # length of pipe in m m.R = po.Var(bounds=(0, None)) # pipe radius in m m.rho = po.Var(bounds=(0, None)) # density of gas in kg per m3 m.a = po.Var(m.t, bounds=(0, None)) # accumulated production in examoles m.dadt = pod.DerivativeVar(m.a, wrt=m.t) # rate of change of accumulated production (equivalent to m.q) def _bal(m, t): return m.dpdt[t] * m.v / m.tau == - m.q[t] * 8.314 * m.qin m.bal = po.Constraint(m.t, rule=_bal) def _hagen_poisueille(m, t): return m.p[t] - m.p_vac[t] == 8 * m.mu * m.L * m.q[t] / (3.14159 * m.R ** 4) m.hagen_poisueille = po.Constraint(m.t, rule=_hagen_poisueille) def _compute_accumulated_production(m, t): return m.dadt[t] == m.q[t] m.compute_accumulated_production = po.Constraint(m.t, rule=_compute_accumulated_production) # defining zero accumulated production at the start m.a[0].fix(0.0) return m
def create_model(spt): """ defining the model """ norm_spt = spt / max(spt) model = po.ConcreteModel() model.t = pod.ContinuousSet(bounds=(0, 1), initialize=norm_spt) model.tau = po.Var() model.temp = po.Var() model.ca = po.Var(model.t, bounds=(0, 50)) model.cb = po.Var(model.t, bounds=(0, 50)) model.dca_dt = pod.DerivativeVar(model.ca, wrt=model.t) model.dcb_dt = pod.DerivativeVar(model.cb, wrt=model.t) model.theta_0 = po.Var() # model parameters model.theta_1 = po.Var() model.alpha_a = po.Var() model.alpha_b = po.Var() model.nu = po.Var() def _material_balance_a(m, t): k = po.exp(m.theta_0 + m.theta_1 * (m.temp - 273.15) / m.temp) return m.dca_dt[t] / m.tau == -k * (m.ca[t]**model.alpha_a) * ( model.cb[t]**model.alpha_b) model.material_balance_a = po.Constraint(model.t, rule=_material_balance_a) def _material_balance_b(m, t): k = po.exp(m.theta_0 + m.theta_1 * (m.temp - 273.15) / m.temp) return m.dcb_dt[t] / m.tau == m.nu * k * (m.ca[t]**model.alpha_a) * ( model.cb[t]**model.alpha_b) model.material_balance_b = po.Constraint(model.t, rule=_material_balance_b) simulator = pod.Simulator(model, package='casadi') return model, simulator
def make_model(horizon=10.0): m = pyo.ConcreteModel() m.comp = pyo.Set(initialize=["A", "B"]) m.time = dae.ContinuousSet(initialize=[0, horizon]) m.stoich = pyo.Param(m.comp, initialize={"A": -1, "B": 1}, mutable=True) m.k_rxn = pyo.Param(initialize=1.0, mutable=True) m.conc = pyo.Var(m.time, m.comp) m.dcdt = dae.DerivativeVar(m.conc, wrt=m.time) m.time_block = pyo.Block(m.time, rule=_block_rule) return m
def create_model(sampling_times): norm_spt = sampling_times / max(sampling_times) m = po.ConcreteModel() m.t = pod.ContinuousSet(bounds=(0, 1), initialize=norm_spt) m.tau = po.Param(initialize=np.max(sampling_times)) # population compartments m.s = po.Var(m.t, bounds=(0, None)) m.i = po.Var(m.t, bounds=(0, None)) m.r = po.Var(m.t, bounds=(0, None)) # differential variables m.dsdt = pod.DerivativeVar(m.s, wrt=m.t) m.didt = pod.DerivativeVar(m.i, wrt=m.t) m.drdt = pod.DerivativeVar(m.r, wrt=m.t) # model parameters m.beta = po.Var() m.gamma = po.Var() """ Model Equations """ def _s_bal(m, t): n = m.s[t] + m.i[t] + m.r[t] return m.dsdt[t] / m.tau == - m.beta * m.i[t] * m.s[t] / n m.s_bal = po.Constraint(m.t, rule=_s_bal) def _i_bal(m, t): n = m.s[t] + m.i[t] + m.r[t] return m.didt[t] / m.tau == m.beta * m.i[t] * m.s[t] / n - m.gamma * m.i[t] m.i_bal = po.Constraint(m.t, rule=_i_bal) def _r_bal(m, t): return m.drdt[t] / m.tau == m.gamma * m.i[t] m.r_bal = po.Constraint(m.t, rule=_r_bal) return m
def _create_variables(self): _model = self._model _parameters = self._parameters assert isinstance(_model, pyomo.core.base.Model) _model.x_local = dae.ContinuousSet(domain=env.Reals, bounds=(_parameters["episode_dist_init"], _parameters["episode_dist_end"]), initialize=(_parameters["episode_dist_init"], _parameters["episode_dist_end"])) _model.v = env.Var(_model.x_local, domain=env.Reals, bounds=_parameters["v_bounds"], initialize=BaseModel._create_const_rule(_parameters["v_init"])) _model.dv_dx = dae.DerivativeVar(_model.v, wrt=_model.x_local, domain=env.Reals, initialize=BaseModel._create_const_rule(0)) _model.d2v_dx2 = dae.DerivativeVar(_model.v, wrt=(_model.x_local, _model.x_local), domain=env.Reals, initialize=BaseModel._create_const_rule(0)) _model.Temp = env.Var(_model.x_local, domain=env.Reals, bounds=_parameters["Temp_bounds"], initialize=BaseModel._create_const_rule(_parameters["Temp_air"])) steady_motor_force = (_model.air_fric_coef * _model.v_target ** 2 + _model.roll_fric_coef * _model.car_mass * _model.grav_const) _model.motor_force = env.Var(_model.x_local, domain=env.Reals, bounds=_parameters["motor_force_bounds"], initialize=BaseModel._create_const_rule(steady_motor_force)) _model.dm_dx = dae.DerivativeVar(_model.motor_force, wrt=_model.x_local, # bounds=_parameters["motor_force_deriv_bounds"], domain=env.Reals, initialize=BaseModel._create_const_rule(0)) _model.d2m_dx2 = dae.DerivativeVar(_model.motor_force, wrt=(_model.x_local, _model.x_local), # bounds=_parameters["motor_force_deriv_bounds"], domain=env.Reals, initialize=BaseModel._create_const_rule(0)) _model.braking_force = env.Var(_model.x_local, domain=env.Reals, bounds=_parameters["braking_force_bounds"], initialize=BaseModel._create_const_rule(0)) _model.db_dx = dae.DerivativeVar(_model.braking_force, wrt=_model.x_local, # bounds=_parameters["motor_force_deriv_bounds"], domain=env.Reals, initialize=BaseModel._create_const_rule(0)) _model.d2b_dx2 = dae.DerivativeVar(_model.braking_force, wrt=(_model.x_local, _model.x_local), # bounds=_parameters["motor_force_deriv_bounds"], domain=env.Reals, initialize=BaseModel._create_const_rule(0)) _model.height = env.Var(_model.x_local, domain=env.Reals, initialize=BaseModel._create_const_rule(0)) _model.dh_dx = dae.DerivativeVar(_model.height, wrt=_model.x_local, domain=env.Reals, initialize=BaseModel._create_const_rule(0))
def create_model(): """ defining the model """ model = po.ConcreteModel() model.t = pod.ContinuousSet(bounds=(0, 1)) model.tau = po.Var() model.ca = po.Var(model.t, bounds=(0, 50)) # set of concentrations in reaction mixture model.dca_dt = pod.DerivativeVar(model.ca, wrt=model.t) model.beta = po.Var() # model parameters def _material_balance(m, t): return m.dca_dt[t] / m.tau == -m.beta * m.ca[t] model.material_balance = po.Constraint(model.t, rule=_material_balance) return model
def create_problem(begin, end): m = aml.ConcreteModel() m.t = dae.ContinuousSet(bounds=(begin, end)) m.x = aml.Var([1, 2], m.t, initialize=1.0) m.u = aml.Var(m.t, bounds=(None, 0.8), initialize=0) m.xdot = dae.DerivativeVar(m.x) def _x1dot(M, i): if i == M.t.first(): return aml.Constraint.Skip return M.xdot[1, i] == (1 - M.x[2, i]**2) * M.x[1, i] - M.x[2, i] + M.u[i] m.x1dotcon = aml.Constraint(m.t, rule=_x1dot) def _x2dot(M, i): if i == M.t.first(): return aml.Constraint.Skip return M.xdot[2, i] == M.x[1, i] m.x2dotcon = aml.Constraint(m.t, rule=_x2dot) def _init(M): t0 = M.t.first() yield M.x[1, t0] == 0 yield M.x[2, t0] == 1 yield aml.ConstraintList.End m.init_conditions = aml.ConstraintList(rule=_init) def _int_rule(M, i): return M.x[1, i]**2 + M.x[2, i]**2 + M.u[i]**2 m.integral = dae.Integral(m.t, wrt=m.t, rule=_int_rule) m.obj = aml.Objective(expr=m.integral) m.init_condition_names = ['init_conditions'] return m
def create_model_dw(spt): m = po.ConcreteModel() tau = max(spt) norm_spt = spt / tau m.t = pod.ContinuousSet(bounds=(0, 1), initialize=norm_spt) # normalized time variable (unitless) m.tau = po.Var(bounds=(0, None)) # batch time in hours m.p = po.Var(m.t, bounds=(0, None)) # pressure in reservoir in MPa m.dpdt = pod.DerivativeVar(m.p, wrt=m.t) # rate of change of pressure per hour m.v = po.Var(bounds=(0, 1)) # the unknown volume of the reservoir in trillion cubic metres m.T = po.Var(bounds=(0, None)) # the temperature in the reservoir, assumed isothermal m.q = po.Var(m.t, bounds=(0, None)) # gas flowrate taken out in examoles per day (10^18) m.p_vac = po.Var(bounds=(0, None)) # outlet vacuum to drive gas extraction in MPa m.mu = po.Var(bounds=(0, None)) # dynamic viscosity of gas in MPa.hr m.L = po.Var(bounds=(0, None)) # length of pipe in m m.R = po.Var(bounds=(0, None)) # pipe radius in m m.rho = po.Var(bounds=(0, None)) # density of gas in kg per m3 def _bal(m, t): return m.dpdt[t] * m.v / m.tau == - m.q[t] * 8.314 * m.qin m.bal = po.Constraint(m.t, rule=_bal) def _darcy_weisbach(m, t): epsilon = 0.005 # pipe roughness factor d = 2 * m.R # diameter in m v_flow = m.q[t] * 1e18 * 16 / (1000 * 157.77) # volumetric flow rate in m3/day u = v_flow / (3.14159 * m.R ** 2) # mean flow velocity in m/day re = m.rho * u * d / m.mu / 1e6 # Reynold's number """ Darcy friction factor, predicted by the Swamee-Jain equation """ f = 0.25 / (po.log10(epsilon / (d * 3.7) + 5.74 / (re ** 0.9))) ** 2 return (m.p[t] - m.p_vac) / m.L == f * m.rho / 2 * u ** 2 / d m.darcy_weisbach = po.Constraint(m.t, rule=_darcy_weisbach) return m
def rp_example2(): """ This example is done multiple ways to test a few common errors where the integrator and fully time-discretized problem differ, and alternative working formulations. Rather than fixing a differential variable, we can add an explicit time variable for the integrator and fix the time variable to the time index for the fully discretized problem. This works as an alternative to the fixed differential variable. """ m = pyo.ConcreteModel() m.time = pyodae.ContinuousSet(initialize=(0.0, 10.0)) m.x = pyo.Var(m.time) m.u = pyo.Var(m.time) m.t = pyo.Var(m.time) m.dxdt = pyodae.DerivativeVar(m.x, wrt=m.time) def diff_eq_rule(m, t): return m.dxdt[t] == m.x[t]**2 - m.u[t] m.diff_eq = pyo.Constraint(m.time, rule=diff_eq_rule) def x_eq_rule(m, t): return m.x[t] == 2.0 * m.t[t] m.x_eq = pyo.Constraint(m.time, rule=x_eq_rule) discretizer = pyo.TransformationFactory('dae.finite_difference') discretizer.apply_to(m, nfe=1, scheme='BACKWARD') m.u[0].fix(1.0) # For fully discretized fix all times at time index m.t[0].fix(m.time.first()) return m
def model(self): m = pyo.ConcreteModel() m.scaling_factor = pyo.Suffix(direction=pyo.Suffix.EXPORT) m.time = dae.ContinuousSet(bounds=(0, 1)) m.space = dae.ContinuousSet(bounds=(0, 1)) m.z = pyo.Var(m.time, m.space) m.dz = dae.DerivativeVar(m.z, wrt=m.time) m.y = pyo.Var(m.time, m.space) m.u = pyo.Var(m.time) m.s = pyo.Var() def de_rule(m, t, x): return m.dz[t, x] == 5 * m.y[t, x] - 10 * m.z[t, x] m.de = pyo.Constraint(m.time, m.space, rule=de_rule) def ae_rule(m, t, x): return m.y[t, x] == 4 + m.z[t, x]**3 m.ae = pyo.Constraint(m.time, m.space, rule=ae_rule) x0 = m.space.first() def ue_rule(m, t): return m.z[t, x0] == 2 * m.u[t] m.ue = pyo.Constraint(m.time, rule=ue_rule) tf, xf = m.time.last(), m.space.last() def se_rule(m): return m.z[tf, xf] == m.s m.se = pyo.Constraint(rule=se_rule) return m
def create_model(demand_factor=1.0): model = pyo.ConcreteModel() # sets model.TIME = dae.ContinuousSet(bounds=(0.0, 24.0)) model.DIS = dae.ContinuousSet(bounds=(0.0, 1.0)) model.S = pyo.Param(initialize=1) model.SCEN = pyo.RangeSet(1, model.S) # links model.LINK = pyo.Set(initialize=[ 'l1', 'l2', 'l3', 'l4', 'l5', 'l6', 'l7', 'l8', 'l9', 'l10', 'l11', 'l12' ]) def rule_startloc(m, l): ll = [ 'l1', 'l2', 'l3', 'l4', 'l5', 'l6', 'l7', 'l8', 'l9', 'l10', 'l11', 'l12' ] ls = [ 'n1', 'n2', 'n3', 'n4', 'n5', 'n6', 'n7', 'n8', 'n9', 'n10', 'n11', 'n12' ] start_locations = dict(zip(ll, ls)) return start_locations[l] model.lstartloc = pyo.Param(model.LINK, initialize=rule_startloc, within=pyo.Any) def rule_endloc(m, l): ll = [ 'l1', 'l2', 'l3', 'l4', 'l5', 'l6', 'l7', 'l8', 'l9', 'l10', 'l11', 'l12' ] ls = [ 'n2', 'n3', 'n4', 'n5', 'n6', 'n7', 'n8', 'n9', 'n10', 'n11', 'n12', 'n13' ] end_locations = dict(zip(ll, ls)) return end_locations[l] model.lendloc = pyo.Param(model.LINK, initialize=rule_endloc, within=pyo.Any) model.ldiam = pyo.Param(model.LINK, initialize=920.0, mutable=True) def rule_llength(m, l): if l == 'l1' or l == 'l12': return 300.0 return 100.0 model.llength = pyo.Param(model.LINK, initialize=rule_llength, mutable=True) def rule_ltype(m, l): if l == 'l1' or l == 'l12': return 'p' return 'a' model.ltype = pyo.Param(model.LINK, initialize=rule_ltype, within=pyo.Any) def link_a_init_rule(m): return (l for l in m.LINK if m.ltype[l] == "a") model.LINK_A = pyo.Set(initialize=link_a_init_rule) def link_p_init_rule(m): return (l for l in m.LINK if m.ltype[l] == "p") model.LINK_P = pyo.Set(initialize=link_p_init_rule) # nodes model.NODE = pyo.Set(initialize=[ 'n1', 'n2', 'n3', 'n4', 'n5', 'n6', 'n7', 'n8', 'n9', 'n10', 'n11', 'n12', 'n13' ]) def rule_pmin(m, n): if n == 'n1': return 57.0 elif n == 'n13': return 39.0 else: return 34.0 model.pmin = pyo.Param(model.NODE, initialize=rule_pmin, mutable=True) def rule_pmax(m, n): if n == 'n13': return 41.0 return 70.0 model.pmax = pyo.Param(model.NODE, initialize=rule_pmax, mutable=True) # supply model.SUP = pyo.Set(initialize=[1]) model.sloc = pyo.Param(model.SUP, initialize='n1', within=pyo.Any) model.smin = pyo.Param(model.SUP, within=pyo.NonNegativeReals, initialize=0.000, mutable=True) model.smax = pyo.Param(model.SUP, within=pyo.NonNegativeReals, initialize=30, mutable=True) model.scost = pyo.Param(model.SUP, within=pyo.NonNegativeReals) # demand model.DEM = pyo.Set(initialize=[1]) model.dloc = pyo.Param(model.DEM, initialize='n13', within=pyo.Any) model.d = pyo.Param(model.DEM, within=pyo.PositiveReals, initialize=10, mutable=True) # physical data model.TDEC = pyo.Param(initialize=9.5) model.eps = pyo.Param(initialize=0.025, within=pyo.PositiveReals) model.z = pyo.Param(initialize=0.80, within=pyo.PositiveReals) model.rhon = pyo.Param(initialize=0.72, within=pyo.PositiveReals) model.R = pyo.Param(initialize=8314.0, within=pyo.PositiveReals) model.M = pyo.Param(initialize=18.0, within=pyo.PositiveReals) model.pi = pyo.Param(initialize=3.14, within=pyo.PositiveReals) model.nu2 = pyo.Param(within=pyo.PositiveReals, mutable=True) model.lam = pyo.Param(model.LINK, within=pyo.PositiveReals, mutable=True) model.A = pyo.Param(model.LINK, within=pyo.NonNegativeReals, mutable=True) model.Tgas = pyo.Param(initialize=293.15, within=pyo.PositiveReals) model.Cp = pyo.Param(initialize=2.34, within=pyo.PositiveReals) model.Cv = pyo.Param(initialize=1.85, within=pyo.PositiveReals) model.gam = pyo.Param(initialize=model.Cp / model.Cv, within=pyo.PositiveReals) model.om = pyo.Param(initialize=(model.gam - 1.0) / model.gam, within=pyo.PositiveReals) # scaling and constants model.ffac = pyo.Param(within=pyo.PositiveReals, initialize=(1.0e+6 * model.rhon) / (24.0 * 3600.0)) model.ffac2 = pyo.Param(within=pyo.PositiveReals, initialize=3600.0 / (1.0e+4 * model.rhon)) model.pfac = pyo.Param(within=pyo.PositiveReals, initialize=1.0e+5) model.pfac2 = pyo.Param(within=pyo.PositiveReals, initialize=1.0e-5) model.dfac = pyo.Param(within=pyo.PositiveReals, initialize=1.0e-3) model.lfac = pyo.Param(within=pyo.PositiveReals, initialize=1.0e+3) model.c1 = pyo.Param(model.LINK, within=pyo.PositiveReals, mutable=True) model.c2 = pyo.Param(model.LINK, within=pyo.PositiveReals, mutable=True) model.c3 = pyo.Param(model.LINK, within=pyo.PositiveReals, mutable=True) model.c4 = pyo.Param(within=pyo.PositiveReals, mutable=True) # cost factors model.ce = pyo.Param(initialize=0.1, within=pyo.NonNegativeReals) model.cd = pyo.Param(initialize=1.0e+6, within=pyo.NonNegativeReals) model.cT = pyo.Param(initialize=1.0e+6, within=pyo.NonNegativeReals) model.cs = pyo.Param(initialize=0.0, within=pyo.NonNegativeReals) # define stochastic info model.rand_d = pyo.Param(model.SCEN, model.DEM, within=pyo.NonNegativeReals, mutable=True) # convert units for input data def rescale_rule(m): for i in m.LINK: m.ldiam[i] = m.ldiam[i] * m.dfac m.llength[i] = m.llength[i] * m.lfac # m.dx[i] = m.llength[i]/float(m.DIS.last()) for i in m.SUP: m.smin[i] = m.smin[ i] * m.ffac * m.ffac2 # from scmx106/day to kg/s and then to scmx10-4/hr m.smax[i] = m.smax[ i] * m.ffac * m.ffac2 # from scmx106/day to kg/s and then to scmx10-4/hr for i in m.DEM: m.d[i] = m.d[i] * m.ffac * m.ffac2 for i in m.NODE: m.pmin[i] = m.pmin[ i] * m.pfac * m.pfac2 # from bar to Pascals and then to bar m.pmax[i] = m.pmax[ i] * m.pfac * m.pfac2 # from bar to Pascals and then to bar rescale_rule(model) def compute_constants(m): for i in m.LINK: m.lam[i] = (2.0 * pyo.log10(3.7 * m.ldiam[i] / (m.eps * m.dfac)))**(-2.0) m.A[i] = (1.0 / 4.0) * m.pi * m.ldiam[i] * m.ldiam[i] m.nu2 = m.gam * m.z * m.R * m.Tgas / m.M m.c1[i] = (m.pfac2 / m.ffac2) * (m.nu2 / m.A[i]) m.c2[i] = m.A[i] * (m.ffac2 / m.pfac2) m.c3[i] = m.A[i] * (m.pfac2 / m.ffac2) * ( 8.0 * m.lam[i] * m.nu2) / (m.pi * m.pi * (m.ldiam[i]**5.0)) m.c4 = (1 / m.ffac2) * (m.Cp * m.Tgas) compute_constants(model) # set stochastic demands def compute_demands_rule(m): for k in m.SCEN: for j in m.DEM: m.rand_d[k, j] = demand_factor * m.d[j] compute_demands_rule(model) def stochd_init(m, k, j, t): # What it should be to match description in paper # if t < m.TDEC: # return m.d[j] # if t >= m.TDEC and t < m.TDEC+5: # return m.rand_d[k,j] # if t >= m.TDEC+5: # return m.d[j] if t < m.TDEC + 1: return m.d[j] if t >= m.TDEC + 1 and t < m.TDEC + 1 + 4.5: return m.rand_d[k, j] if t >= m.TDEC + 1 + 4.5: return m.d[j] model.stochd = pyo.Param(model.SCEN, model.DEM, model.TIME, within=pyo.PositiveReals, mutable=True, default=stochd_init) # define temporal variables def p_bounds_rule(m, k, j, t): return pyo.value(m.pmin[j]), pyo.value(m.pmax[j]) model.p = pyo.Var(model.SCEN, model.NODE, model.TIME, bounds=p_bounds_rule, initialize=50.0) model.dp = pyo.Var(model.SCEN, model.LINK_A, model.TIME, bounds=(0.0, 100.0), initialize=10.0) model.fin = pyo.Var(model.SCEN, model.LINK, model.TIME, bounds=(1.0, 500.0), initialize=100.0) model.fout = pyo.Var(model.SCEN, model.LINK, model.TIME, bounds=(1.0, 500.0), initialize=100.0) def s_bounds_rule(m, k, j, t): return 0.01, pyo.value(m.smax[j]) model.s = pyo.Var(model.SCEN, model.SUP, model.TIME, bounds=s_bounds_rule, initialize=10.0) model.dem = pyo.Var(model.SCEN, model.DEM, model.TIME, initialize=100.0) model.pow = pyo.Var(model.SCEN, model.LINK_A, model.TIME, bounds=(0.0, 3000.0), initialize=1000.0) model.slack = pyo.Var(model.SCEN, model.LINK, model.TIME, model.DIS, bounds=(0.0, None), initialize=10.0) # define spatio-temporal variables # average 55.7278214666423 model.px = pyo.Var(model.SCEN, model.LINK, model.TIME, model.DIS, bounds=(10.0, 100.0), initialize=50.0) # average 43.19700578593625 model.fx = pyo.Var(model.SCEN, model.LINK, model.TIME, model.DIS, bounds=(1.0, 100.0), initialize=100.0) # define derivatives model.dpxdt = dae.DerivativeVar(model.px, wrt=model.TIME, initialize=0) model.dpxdx = dae.DerivativeVar(model.px, wrt=model.DIS, initialize=0) model.dfxdt = dae.DerivativeVar(model.fx, wrt=model.TIME, initialize=0) model.dfxdx = dae.DerivativeVar(model.fx, wrt=model.DIS, initialize=0) # ----------- MODEL -------------- # compressor equations def powereq_rule(m, j, i, t): return m.pow[j, i, t] == m.c4 * m.fin[j, i, t] * ( ((m.p[j, m.lstartloc[i], t] + m.dp[j, i, t]) / m.p[j, m.lstartloc[i], t])**m.om - 1.0) model.powereq = pyo.Constraint(model.SCEN, model.LINK_A, model.TIME, rule=powereq_rule) # cvar model model.cvar_lambda = pyo.Param(initialize=0.0) model.nu = pyo.Var(initialize=100.0) model.phi = pyo.Var(model.SCEN, bounds=(0.0, None), initialize=100.0) def cvarcost_rule(m): return (1.0 / m.S) * sum( (m.phi[k] / (1.0 - 0.95) + m.nu) for k in m.SCEN) model.cvarcost = pyo.Expression(rule=cvarcost_rule) # node balances def nodeeq_rule(m, k, i, t): return sum(m.fout[k, j, t] for j in m.LINK if m.lendloc[j] == i) + \ sum(m.s[k, j, t] for j in m.SUP if m.sloc[j] == i) - \ sum(m.fin[k, j, t] for j in m.LINK if m.lstartloc[j] == i) - \ sum(m.dem[k, j, t] for j in m.DEM if m.dloc[j] == i) == 0.0 model.nodeeq = pyo.Constraint(model.SCEN, model.NODE, model.TIME, rule=nodeeq_rule) # boundary conditions flow def flow_start_rule(m, j, i, t): return m.fx[j, i, t, m.DIS.first()] == m.fin[j, i, t] model.flow_start = pyo.Constraint(model.SCEN, model.LINK, model.TIME, rule=flow_start_rule) def flow_end_rule(m, j, i, t): return m.fx[j, i, t, m.DIS.last()] == m.fout[j, i, t] model.flow_end = pyo.Constraint(model.SCEN, model.LINK, model.TIME, rule=flow_end_rule) # First PDE for gas network model def flow_rule(m, j, i, t, k): if t == m.TIME.first() or k == m.DIS.last(): return pyo.Constraint.Skip # Do not apply pde at initial time or final location return m.dpxdt[j, i, t, k] / 3600.0 + m.c1[i] / m.llength[i] * m.dfxdx[ j, i, t, k] == 0 model.flow = pyo.Constraint(model.SCEN, model.LINK, model.TIME, model.DIS, rule=flow_rule) # Second PDE for gas network model def press_rule(m, j, i, t, k): if t == m.TIME.first() or k == m.DIS.last(): return pyo.Constraint.Skip # Do not apply pde at initial time or final location return m.dfxdt[j, i, t, k] / 3600 == -m.c2[i] / m.llength[i] * m.dpxdx[ j, i, t, k] - m.slack[j, i, t, k] model.press = pyo.Constraint(model.SCEN, model.LINK, model.TIME, model.DIS, rule=press_rule) def slackeq_rule(m, j, i, t, k): if t == m.TIME.last(): return pyo.Constraint.Skip return m.slack[j, i, t, k] * m.px[j, i, t, k] == m.c3[i] * m.fx[ j, i, t, k] * m.fx[j, i, t, k] model.slackeq = pyo.Constraint(model.SCEN, model.LINK, model.TIME, model.DIS, rule=slackeq_rule) # boundary conditions pressure, passive links def presspas_start_rule(m, j, i, t): return m.px[j, i, t, m.DIS.first()] == m.p[j, m.lstartloc[i], t] model.presspas_start = pyo.Constraint(model.SCEN, model.LINK_P, model.TIME, rule=presspas_start_rule) def presspas_end_rule(m, j, i, t): return m.px[j, i, t, m.DIS.last()] == m.p[j, m.lendloc[i], t] model.presspas_end = pyo.Constraint(model.SCEN, model.LINK_P, model.TIME, rule=presspas_end_rule) # boundary conditions pressure, active links def pressact_start_rule(m, j, i, t): return m.px[j, i, t, m.DIS.first()] == m.p[j, m.lstartloc[i], t] + m.dp[j, i, t] model.pressact_start = pyo.Constraint(model.SCEN, model.LINK_A, model.TIME, rule=pressact_start_rule) def pressact_end_rule(m, j, i, t): return m.px[j, i, t, m.DIS.last()] == m.p[j, m.lendloc[i], t] model.pressact_end = pyo.Constraint(model.SCEN, model.LINK_A, model.TIME, rule=pressact_end_rule) # fix pressure at supply nodes def suppres_rule(m, k, j, t): return m.p[k, m.sloc[j], t] == m.pmin[m.sloc[j]] model.suppres = pyo.Constraint(model.SCEN, model.SUP, model.TIME, rule=suppres_rule) # discharge pressure for compressors def dispress_rule(m, j, i, t): return m.p[j, m.lstartloc[i], t] + m.dp[j, i, t] <= m.pmax[m.lstartloc[i]] model.dispress = pyo.Constraint(model.SCEN, model.LINK_A, model.TIME, rule=dispress_rule) # ss constraints def flow_ss_rule(m, j, i, k): if k == m.DIS.last(): return pyo.Constraint.Skip return m.dfxdx[j, i, m.TIME.first(), k] == 0.0 model.flow_ss = pyo.Constraint(model.SCEN, model.LINK, model.DIS, rule=flow_ss_rule) def pres_ss_rule(m, j, i, k): if k == m.DIS.last(): return pyo.Constraint.Skip return 0.0 == -m.c2[i] / m.llength[i] * m.dpxdx[ j, i, m.TIME.first(), k] - m.slack[j, i, m.TIME.first(), k] model.pres_ss = pyo.Constraint(model.SCEN, model.LINK, model.DIS, rule=pres_ss_rule) # non-anticipativity constraints def nonantdq_rule(m, j, i, t): if j == 1: return pyo.Constraint.Skip if t >= m.TDEC + 1: return pyo.Constraint.Skip return m.dp[j, i, t] == m.dp[1, i, t] model.nonantdq = pyo.Constraint(model.SCEN, model.LINK_A, model.TIME, rule=nonantdq_rule) def nonantde_rule(m, j, i, t): if j == 1: return pyo.Constraint.Skip if t >= m.TDEC + 1: return pyo.Constraint.Skip return m.dem[j, i, t] == m.dem[1, i, t] model.nonantde = pyo.Constraint(model.SCEN, model.DEM, model.TIME, rule=nonantde_rule) # discretize model discretizer = pyo.TransformationFactory('dae.finite_difference') discretizer.apply_to(model, nfe=1, wrt=model.DIS, scheme='FORWARD') discretizer2 = pyo.TransformationFactory('dae.collocation') #discretizer2.apply_to(model, nfe=47, ncp=1, wrt=model.TIME, scheme='LAGRANGE-RADAU') # discretizer.apply_to(model, nfe=48, wrt=model.TIME, scheme='BACKWARD') # What it should be to match description in paper discretizer.apply_to(model, nfe=48, wrt=model.TIME, scheme='BACKWARD') TimeStep = model.TIME[2] - model.TIME[1] def supcost_rule(m, k): return sum(m.cs * m.s[k, j, t] * TimeStep for j in m.SUP for t in m.TIME.get_finite_elements()) model.supcost = pyo.Expression(model.SCEN, rule=supcost_rule) def boostcost_rule(m, k): return sum(m.ce * m.pow[k, j, t] * TimeStep for j in m.LINK_A for t in m.TIME.get_finite_elements()) model.boostcost = pyo.Expression(model.SCEN, rule=boostcost_rule) def trackcost_rule(m, k): return sum(m.cd * (m.dem[k, j, t] - m.stochd[k, j, t])**2.0 for j in m.DEM for t in m.TIME.get_finite_elements()) model.trackcost = pyo.Expression(model.SCEN, rule=trackcost_rule) def sspcost_rule(m, k): return sum( m.cT * (m.px[k, i, m.TIME.last(), j] - m.px[k, i, m.TIME.first(), j])**2.0 for i in m.LINK for j in m.DIS) model.sspcost = pyo.Expression(model.SCEN, rule=sspcost_rule) def ssfcost_rule(m, k): return sum( m.cT * (m.fx[k, i, m.TIME.last(), j] - m.fx[k, i, m.TIME.first(), j])**2.0 for i in m.LINK for j in m.DIS) model.ssfcost = pyo.Expression(model.SCEN, rule=ssfcost_rule) def cost_rule(m, k): return 1e-6 * (m.supcost[k] + m.boostcost[k] + m.trackcost[k] + m.sspcost[k] + m.ssfcost[k]) model.cost = pyo.Expression(model.SCEN, rule=cost_rule) def mcost_rule(m): return sum(m.cost[k] for k in m.SCEN) model.mcost = pyo.Expression(rule=mcost_rule) model.FirstStageCost = pyo.Expression(expr=0.0) model.SecondStageCost = pyo.Expression(rule=mcost_rule) model.obj = pyo.Objective(expr=model.FirstStageCost + model.SecondStageCost) return model
# This is a file for testing miscellaneous code snippets from the DAE chapter import pyomo.environ as pyo import pyomo.dae as dae m = pyo.ConcreteModel() m.t = dae.ContinuousSet(bounds=(0, 1)) m.x1 = pyo.Var(m.t) # @second-deriv: m.dx1dt2 = dae.DerivativeVar(m.x1, wrt=(m.t, m.t)) # @:second-deriv # @finite-diff: discretizer = pyo.TransformationFactory('dae.finite_difference') discretizer.apply_to(m, nfe=20, wrt=m.t, scheme='BACKWARD') # @:finite-diff print('First Model') print(len(m.t)) print(len(m.x1)) m = pyo.ConcreteModel() m.t1 = dae.ContinuousSet(bounds=(0, 1)) m.t2 = dae.ContinuousSet(bounds=(0, 1)) m.x1 = pyo.Var(m.t1, m.t2) m.dx1dt2 = dae.DerivativeVar(m.x1, wrt=(m.t1, m.t2)) # @finite-diff2: # Apply multiple finite difference schemes discretizer = pyo.TransformationFactory('dae.finite_difference')
def create_mdoel(modelparameters): model = po.ConcreteModel() """"defining fixed parameters""" model.i = po.Set(initialize=[ "Nitric", "Toluene", "O-MNT", "P-MNT", "M-MNT", "DNT", "H2O" ]) model.biot_number = po.Param(initialize=modelparameters.Bi) model.frequency_factor = po.Param( initialize=modelparameters.frequency_factor) model.activation_energy = po.Param( initialize=modelparameters.activation_energy) model.d_catalyst = po.Param(initialize=modelparameters.d_catalyst) model.u_super = po.Param(initialize=modelparameters.u_super) model.D_ea = po.Param(initialize=modelparameters.D_ea) model.Cp_Nitric = po.Param(initialize=modelparameters.Cp_Nitric) model.Cp_H2O = po.Param(initialize=75.399) model.Cp_Toluene = po.Param(initialize=157) model.Cp_MNT = po.Param(initialize=202.1) model.Cp_DNT = po.Var(initialize=255) model.v_frac_aq = po.Param(initialize=modelparameters.v_frac_aq) model.Selectivity = po.Param(model.i, initialize={ "Nitric": modelparameters.selectivity["Nitric"], "Toluene": modelparameters.selectivity["Toluene"], "O-MNT": modelparameters.selectivity["O-MNT"], "P-MNT": modelparameters.selectivity["P-MNT"], "M-MNT": modelparameters.selectivity["M-MNT"], "DNT": modelparameters.selectivity["DNT"], "H2O": modelparameters.selectivity["H2O"] }) model.reaction_enthalpy = po.Param( initialize=modelparameters.reaction_enthalpy) model.a_s = po.Param(initialize=modelparameters.a_s) model.hf = po.Param(initialize=modelparameters.hf) """defining model variables""" model.z = pod.ContinuousSet(bounds=(0, modelparameters.length)) model.global_effectiveness_factor = po.Var(model.z) model.reaction_rate = po.Var(model.z) model.C = po.Var(model.z, model.i) """model.Cp_H2O = po.Var(model.z) model.Cp_Toluene = po.Var(model.z) model.Cp_MNT = po.Var(model.z) model.Cp_DNT = po.Var(model.z)""" model.intrinsic_rate_constant = po.Var(model.z) model.dC_dz = pod.DerivativeVar(model.C, wrt=model.z) """model.cat_temp = po.Var(model.z)""" model.T = po.Var(model.z) model.dT_dz = pod.DerivativeVar(model.T, wrt=model.z) """intial conditions""" model.C[0, "Nitric"].fix(modelparameters.C_B0) model.C[0, "Toluene"].fix(modelparameters.C_A0) model.C[0, "H2O"].fix(modelparameters.C_W0) model.C[0, "O-MNT"].fix(0) model.C[0, "P-MNT"].fix(0) model.C[0, "M-MNT"].fix(0) model.C[0, "DNT"].fix(0) model.T[0].fix(modelparameters.feed_temperature) def _calculate_intrinsic_rate_constant(m, z): return m.intrinsic_rate_constant[z] == m.frequency_factor * po.exp( -m.activation_energy / m.T[z]) model.calculate_intrinsic_rate_constant = po.Constraint( model.z, rule=_calculate_intrinsic_rate_constant) def _calcualte_global_effectiveness_factor(m, z): catalyst_rate_constant = m.intrinsic_rate_constant[z] * m.C[z, "Nitric"] thielemodulus = Thiele_Modulus(Diameter_Particle=m.d_catalyst, Intrinsic_Rate=catalyst_rate_constant, D_ea=m.D_ea) effectiveness_factor = po.tanh(thielemodulus) / thielemodulus return m.global_effectiveness_factor[z] == ( (1 / effectiveness_factor) + ((thielemodulus**2) / m.biot_number))**(-1) model.calculate_global_effectiveness_factor = po.Constraint( model.z, rule=_calcualte_global_effectiveness_factor) def _calculate_reaction_rate(m, z): return m.reaction_rate[ z] == m.v_frac_aq * m.global_effectiveness_factor[ z] * m.intrinsic_rate_constant[z] * m.C[z, "Nitric"] * m.C[ z, "Toluene"] model.calculate_reaction_rate = po.Constraint( model.z, rule=_calculate_reaction_rate) #-----------------------------------------------------# #Heat Capacities def _calculate_Cp_H2O(m, z): return m.Cp_H2O[z] == (28.07 - 0.2817 * m.T[z] + 1.25E-3 * m.T[z]**2 - 2.48E-6 * m.T[z]**3) * (1000 * 0.018015 ) #J/mol.K. model.calculate_Cp_H2O = po.Constraint(model.z, rule=_calculate_Cp_H2O) #https://syeilendrapramuditya.wordpress.com/2011/08/20/water-thermodynamic-properties/ (Kj/KgK) #GC method for CP estimations of organic liquids, using non-hierarchic method as described in the paper below #https: // pubs.acs.org / doi / full / 10.1021 / ie071228z?src = recsys & mobileUi = 0 def _calculate_Cp_Toluene(m, z): return m.Cp_Toluene[z] == 119.77 - 0.92 * (m.T[z] / 100) + 4.66 * ( m.T[z] / 100)**2 #j/mol.k. model.calculate_Cp_Toluene = po.Constraint(model.z, rule=_calculate_Cp_Toluene) def _calculate_Cp_MNT(m, z): return m.Cp_MNT[z] == 501.47 - 180.86 * (m.T[z] / 100) + 28.76 * ( m.T[z] / 100)**2 #j/mol.k. model.calculate_Cp_MNT = po.Constraint(model.z, rule=_calculate_Cp_MNT) def _calculate_Cp_DNT(m, z): return m.Cp_DNT[z] == 883.17 - 360.8 * (m.T[z] / 100) + 52.86 * ( m.T[z] / 100)**2 #j/mol.k. model.calculate_Cp_DNT = po.Constraint(model.z, rule=_calculate_Cp_DNT) def _calculate_cat_temp(m, z): return m.cat_temp[z] == m.T[z] - ( (m.reaction_rate[z] * m.reaction_enthalpy) * (1 / (m.hf * m.a_s))) model.calculate_cat_temp = po.Constraint(model.z, rule=_calculate_cat_temp) #-----------------------------------------------------# #Material Balances def _material_balance_reactants(m, z, i): return m.dC_dz[ z, i] == -(1 / m.u_super) * (m.reaction_rate[z]) * (m.Selectivity[i]) model.material_balance_nitric = po.Constraint( model.z, model.i, rule=_material_balance_reactants) #-----------------------------------------------------# #Energy Balances def _Energy_balance(m, z): cp_avg = m.C[z, "Nitric"] * m.Cp_Nitric + m.C[ z, "Toluene"] * m.Cp_Toluene + m.Cp_MNT * ( m.C[z, "O-MNT"] + m.C[z, "P-MNT"] + m.C[z, "M-MNT"] ) + m.C[z, "DNT"] * m.Cp_DNT + m.Cp_H2O * m.C[z, "H2O"] return m.dT_dz[z] == (1 / (m.u_super * cp_avg)) * (-m.reaction_rate[z] * m.reaction_enthalpy) model.Energy_balance = po.Constraint(model.z, rule=_Energy_balance) return model
def build_burgers_model(self, nfe_x=50, nfe_t=50, start_t=0, end_t=1, add_init_conditions=True): dt = (end_t - start_t) / float(nfe_t) start_x = 0 end_x = 1 dx = (end_x - start_x) / float(nfe_x) m = pe.Block(concrete=True) m.omega = pe.Param(initialize=0.02) m.v = pe.Param(initialize=0.01) m.r = pe.Param(initialize=0) m.x = dae.ContinuousSet(bounds=(start_x, end_x)) m.t = dae.ContinuousSet(bounds=(start_t, end_t)) m.y = pe.Var(m.x, m.t) m.dydt = dae.DerivativeVar(m.y, wrt=m.t) m.dydx = dae.DerivativeVar(m.y, wrt=m.x) m.dydx2 = dae.DerivativeVar(m.y, wrt=(m.x, m.x)) m.u = pe.Var(m.x, m.t) def _y_init_rule(m, x): if x <= 0.5 * end_x: return 1 return 0 m.y0 = pe.Param(m.x, default=_y_init_rule) def _upper_x_bound(m, t): return m.y[end_x, t] == 0 m.upper_x_bound = pe.Constraint(m.t, rule=_upper_x_bound) def _lower_x_bound(m, t): return m.y[start_x, t] == 0 m.lower_x_bound = pe.Constraint(m.t, rule=_lower_x_bound) def _upper_x_ubound(m, t): return m.u[end_x, t] == 0 m.upper_x_ubound = pe.Constraint(m.t, rule=_upper_x_ubound) def _lower_x_ubound(m, t): return m.u[start_x, t] == 0 m.lower_x_ubound = pe.Constraint(m.t, rule=_lower_x_ubound) def _lower_t_bound(m, x): if x == start_x or x == end_x: return pe.Constraint.Skip return m.y[x, start_t] == m.y0[x] def _lower_t_ubound(m, x): if x == start_x or x == end_x: return pe.Constraint.Skip return m.u[x, start_t] == 0 if add_init_conditions: m.lower_t_bound = pe.Constraint(m.x, rule=_lower_t_bound) m.lower_t_ubound = pe.Constraint(m.x, rule=_lower_t_ubound) # PDE def _pde(m, x, t): if t == start_t or x == end_x or x == start_x: e = pe.Constraint.Skip else: # print(foo.last_t, t-dt, abs(foo.last_t - (t-dt))) # assert math.isclose(foo.last_t, t - dt, abs_tol=1e-6) e = m.dydt[x, t] - m.v * m.dydx2[x, t] + m.dydx[x, t] * m.y[ x, t] == m.r + m.u[x, self.last_t] self.last_t = t return e m.pde = pe.Constraint(m.x, m.t, rule=_pde) # Discretize Model disc = pe.TransformationFactory('dae.finite_difference') disc.apply_to(m, nfe=nfe_t, wrt=m.t, scheme='BACKWARD') disc.apply_to(m, nfe=nfe_x, wrt=m.x, scheme='CENTRAL') # Solve control problem using Pyomo.DAE Integrals def _intX(m, x, t): return (m.y[x, t] - m.y0[x])**2 + m.omega * m.u[x, t]**2 m.intX = dae.Integral(m.x, m.t, wrt=m.x, rule=_intX) def _intT(m, t): return m.intX[t] m.intT = dae.Integral(m.t, wrt=m.t, rule=_intT) def _obj(m): e = 0.5 * m.intT for x in sorted(m.x): if x == start_x or x == end_x: pass else: e += 0.5 * 0.5 * dx * dt * m.omega * m.u[x, start_t]**2 return e m.obj = pe.Objective(rule=_obj) return m
def create_model(spt): model = po.ConcreteModel() model.t = pod.ContinuousSet(bounds=(0, 1), initialize=spt) model.tau = po.Var(bounds=(0, None)) model.y1 = po.Var(model.t) model.y2 = po.Var(model.t) model.y3 = po.Var(model.t) model.y4 = po.Var(model.t) model.x1 = po.Var() model.x2 = po.Var() model.x3 = po.Var() model.x4 = po.Var() model.k1 = po.Var() model.k2 = po.Var() model.k1r = po.Var() model.beta1 = po.Var() model.beta2 = po.Var() model.dy1dt = pod.DerivativeVar(model.y1, wrt=model.t) model.dy2dt = pod.DerivativeVar(model.y2, wrt=model.t) model.dy3dt = pod.DerivativeVar(model.y3, wrt=model.t) def _ode_1(m, t): s = (-2 * m.x3 + m.x4 + 2 * m.y1[t] - m.y2[t] + m.y3[t]) / ( m.y1[t] + m.beta1 * (-m.x3 + m.x4 + m.y1[t] - m.y2[t]) + m.beta2 * m.y3[t]) return m.dy1dt[t] == m.tau * (-m.k2 * m.y1[t] * m.y2[t] * s) model.ode_1 = po.Constraint(model.t, rule=_ode_1) def _ode_2(m, t): s = (-2 * m.x3 + m.x4 + 2 * m.y1[t] - m.y2[t] + m.y3[t]) / ( m.y1[t] + m.beta1 * (-m.x3 + m.x4 + m.y1[t] - m.y2[t]) + m.beta2 * m.y3[t]) return m.dy2dt[t] == m.tau * ( -m.k1 * m.y2[t] * (m.x2 + 2 * m.x3 - m.x4 - 2 * m.y1[t] + m.y2[t] - m.y3[t]) - m.k2 * m.y1[t] * m.y2[t] * s + m.k1r * m.beta1 * (-m.x3 + m.x4 + m.y1[t] - m.y2[t]) * s) model.ode_2 = po.Constraint(model.t, rule=_ode_2) def _ode_3(m, t): s = (-2 * m.x3 + m.x4 + 2 * m.y1[t] - m.y2[t] + m.y3[t]) / ( m.y1[t] + m.beta1 * (-m.x3 + m.x4 + m.y1[t] - m.y2[t]) + m.beta2 * m.y3[t]) return m.dy3dt[t] == m.tau * ( m.k1 * (m.x3 - m.y1[t] - m.y3[t]) * (m.x2 + 2 * m.x3 - m.x4 - 2 * m.y1[t] + m.y2[t] - m.y3[t]) + m.k2 * m.y1[t] * m.y2[t] * s - 0.5 * m.k1r * m.beta2 * m.y3[t] * s) model.ode_3 = po.Constraint(model.t, rule=_ode_3) def _ae_1(m, t): return m.y4[t] == m.y1[0] - m.y1[t] - m.y3[t] model.ae_1 = po.Constraint(model.t, rule=_ae_1) return model
def biofmodel(y0, u, ymeas, sigma, tmeas, ig, lb, ub, T, N): model = py.ConcreteModel() ft = T total_elements = int(N) element_length = ft / total_elements scheme_name = 'LAGRANGE-LEGENDRE' # scheme_name = 'LAGRANGE-RADAU' discretizer = py.TransformationFactory('dae.collocation') d = 4 model.tau = pyd.ContinuousSet(bounds=(0, ft)) discretizer.apply_to(model, wrt=model.tau, nfe=total_elements, ncp=d, scheme=scheme_name) model.t = pyd.ContinuousSet(initialize=np.round( np.linspace(ft / total_elements, ft, total_elements), 1).tolist(), bounds=(0, ft)) # dynamic ata model.meas_t = py.Set(initialize=tmeas, within=model.t) model.x1_meas = py.Param( model.meas_t, initialize={tmeas[k]: ymeas[0][k] for k in range(np.shape(tmeas)[0])}) model.x2_meas = py.Param( model.meas_t, initialize={tmeas[k]: ymeas[1][k] for k in range(np.shape(tmeas)[0])}) model.theta_idx = py.Set(initialize=list(range(np.shape(ig)[0]))) theta_lb_dict = dict(list(enumerate(lb))) theta_ub_dict = dict(list(enumerate(ub))) theta_dict = dict(list(enumerate(ig))) def parmbounds(model, i): return (theta_lb_dict[i], theta_ub_dict[i]) # declare model parameters model.theta = py.Var(model.theta_idx, initialize=theta_dict, bounds=parmbounds) model.tprime = py.Set(initialize=sorted(model.tau)) uk = np.zeros([np.shape(u)[0], np.shape(sorted(model.tau))[0]]) for i in range(total_elements): uk[0][(d + 1) * i + 1:(d + 1) * (i + 1) + 1] = [u[0][i]] * (d + 1) uk[1][(d + 1) * i + 1:(d + 1) * (i + 1) + 1] = [u[1][i]] * (d + 1) model.u1 = py.Param(model.tprime, initialize={ sorted(model.tau)[k]: uk[0][k] for k in range(np.shape(sorted(model.tau))[0]) }) model.u2 = py.Param(model.tprime, initialize={ sorted(model.tau)[k]: uk[1][k] for k in range(np.shape(sorted(model.tau))[0]) }) # declare differential variables model.x1 = py.Var(model.t, within=py.NonNegativeReals, bounds=(0, np.inf)) model.x2 = py.Var(model.t, within=py.NonNegativeReals, bounds=(0, np.inf)) # declare derivatives model.dx1dt = pyd.DerivativeVar(model.x1, wrt=model.t) model.dx2dt = pyd.DerivativeVar(model.x2, wrt=model.t) def diffeqn1(model, t): if model.t == 0: return py.Constraint.Skip return model.dx1dt[t] == ((model.theta[0] * model.x2[t] / (model.theta[1] + model.x2[t])) - model.u1[t] - model.theta[3]) * model.x1[t] model.x1cons = py.Constraint(model.t, rule=diffeqn1) def diffeqn2(model, t): if model.t == 0: return py.Constraint.Skip return model.dx2dt[t] == ( (-(model.theta[0] * model.x2[t] / (model.theta[1] + model.x2[t])) * model.x1[t]) / model.theta[2]) + model.u1[t] * (model.u2[t] - model.x2[t]) model.x2cons = py.Constraint(model.t, rule=diffeqn2) def init_conditions(model): yield model.x1[0] == y0[0] yield model.x2[0] == y0[1] model.init_cond = py.ConstraintList(rule=init_conditions) discretizer.apply_to(model, wrt=model.t, nfe=total_elements, ncp=d, scheme=scheme_name) def obj_expression(model): chisq_1 = sum((((model.x1_meas[j] - model.x1[j])**2) / sigma[0][0]) + (((model.x2_meas[j] - model.x2[j])**2) / sigma[1][1]) for j in model.meas_t) obj_fun = chisq_1 return obj_fun model.objfun = py.Objective(rule=obj_expression) return model
def optkm1(y0, u, ymeas, td, sigma, tmeas, ig, lb, ub, T, N, scheme_name): model = py.ConcreteModel() # ft = int(T) ft = (T) total_elements = int(N) element_length = (ft / total_elements) scheme_name = 'LAGRANGE-LEGENDRE' scheme_name = 'LAGRANGE-RADAU' d = 4 model.t = pyd.ContinuousSet(initialize=np.linspace( ft / total_elements, ft, total_elements).tolist(), bounds=(0, ft)) # model.t = pyd.ContinuousSet(initialize = sorted(model.tau), bounds = (0,ft)) # Data: Experient 1 model.meas_t_1 = py.Set(initialize=tmeas) #, within = model.t) model.tk = py.Set(initialize=td) #, within = model.t) model.x1_1_meas = py.Param( model.meas_t_1, initialize={tmeas[k]: ymeas[0][k] for k in range(np.shape(tmeas)[0])}) model.x2_1_meas = py.Param( model.meas_t_1, initialize={tmeas[k]: ymeas[1][k] for k in range(np.shape(tmeas)[0])}) uk = np.zeros([2, np.shape(td)[0]]) for i in range(total_elements): uk[0][(d + 1) * i + 1:(d + 1) * (i + 1) + 1] = [u[0][i]] * ( d + 1 ) # check the float here. A float is coomin under the function. uk[1][(d + 1) * i + 1:(d + 1) * (i + 1) + 1] = [u[1][i]] * (d + 1) model.u1 = py.Param( model.tk, initialize={td[k]: uk[0][k] for k in range(np.shape(td)[0])}) model.u2 = py.Param( model.tk, initialize={td[k]: uk[1][k] for k in range(np.shape(td)[0])}) model.theta_idx = py.Set(initialize=list(range(np.shape(ig)[0]))) theta_lb_dict = dict(list(enumerate(lb))) theta_ub_dict = dict(list(enumerate(ub))) theta_dict = dict(list(enumerate(ig))) def parmbounds(model, i): return (theta_lb_dict[i], theta_ub_dict[i]) # declare model parameters model.theta = py.Var(model.theta_idx, initialize=theta_dict, bounds=parmbounds) # declare differential variables model.x1 = py.Var(model.t, within=py.NonNegativeReals, bounds=(0, np.inf)) model.x2 = py.Var(model.t, within=py.NonNegativeReals, bounds=(0, np.inf)) # declare differential variables for batch case n_exp = 3 expv = list(range(n_exp)) model.x1 = py.Var(expv, model.t, within=py.NonNegativeReals, bounds=(0, np.inf)) model.x2 = py.Var(expv, model.t, within=py.NonNegativeReals, bounds=(0, np.inf)) # declare derivatives model.dx1dt = pyd.DerivativeVar(model.x1, wrt=model.t) model.dx2dt = pyd.DerivativeVar(model.x2, wrt=model.t) # declare derivatives for batch case model.dx1dt = pyd.DerivativeVar(expv, model.x1, wrt=model.t) model.dx2dt = pyd.DerivativeVar(expv, model.x2, wrt=model.t) def diffeqn1(model, t): if model.t == 0: return py.Constraint.Skip return model.dx1dt[t] == ((model.theta[0] * model.x2[t] / (model.theta[1] + model.x2[t])) - model.u1[t] - model.theta[3]) * model.x1[t] model.x1cons = py.Constraint(model.t, rule=diffeqn1) def diffeqn2(model, t): if model.t == 0: return py.Constraint.Skip return model.dx2dt[t] == ( (-(model.theta[0] * model.x2[t] / (model.theta[1] + model.x2[t])) * model.x1[t]) / model.theta[2]) + model.u1[t] * (model.u2[t] - model.x2[t]) model.x2cons = py.Constraint(model.t, rule=diffeqn2) def init_conditions(model): yield model.x1[0] == y0[0] yield model.x2[0] == y0[1] model.init_cond = py.ConstraintList(rule=init_conditions) # discretize model using orthogonal collocation discretizer = py.TransformationFactory('dae.collocation') discretizer.apply_to(model, wrt=model.t, nfe=total_elements, ncp=d, scheme=scheme_name) def obj_expression(model): chisq_1 = sum((((model.x1_1_meas[j] - model.x1[j])**2) / sigma[0]) + (((model.x2_1_meas[j] - model.x2[j])**2) / sigma[1]) for j in model.meas_t_1) obj_fun = chisq_1 return obj_fun model.objfun = py.Objective(rule=obj_expression) return model
def make_model(horizon=5, nfe=10, ncp=2): """ The simplest DAE I can think of. An isothermal CSTR with one reaction. No nlp solver should have trouble with this one. Other than the flow_out*conc_out term in the material_balances, this model is entirely linear. """ m = aml.ConcreteModel() m.time = dae.ContinuousSet(bounds=(0, horizon)) m.components = aml.Set(initialize=['A', 'B']) m.volume = aml.Param(initialize=1.0) m.max_height = aml.Var(initialize=1.0) m.max_height.fix() stoich_dict = { 'A': -1, 'B': 1, } m.stoich = aml.Param(m.components, initialize=stoich_dict) m.k_rxn = aml.Param(initialize=1.0) m.rxn_order = aml.Param(initialize=1, domain=aml.Integers) # Variables m.flow_in = aml.Var(m.time) m.flow_out = aml.Var(m.time) m.conc_in = aml.Var(m.time, m.components) m.conc = aml.Var(m.time, m.components) m.rate = aml.Var(m.time, m.components) m.dcdt = dae.DerivativeVar(m.conc, wrt=m.time) # Equations def mb_rule(m, t, j): return ( m.volume*m.dcdt[t, j] == m.flow_in[t]*m.conc_in[t, j] - m.flow_out[t]*m.conc[t, j] + m.volume*m.rate[t, j] ) m.material_balance = aml.Constraint(m.time, m.components, rule=mb_rule) def flow_rule(m, t): return m.flow_in[t] == m.flow_out[t] m.flow_eqn = aml.Constraint(m.time, rule=flow_rule) def rate_rule(m, t, j): return m.rate[t, j] == m.stoich[j]*m.k_rxn*m.conc[t, 'A']**m.rxn_order m.rate_eqn = aml.Constraint(m.time, m.components, rule=rate_rule) disc = aml.TransformationFactory('dae.collocation') disc.apply_to(m, wrt=m.time, nfe=nfe, ncp=2, scheme='LAGRANGE-RADAU') # Degrees of freedom: m.conc_in[:, 'A'].fix(5.0) m.conc_in[:, 'B'].fix(0.0) m.conc[0, 'A'].fix(0.0) m.conc[0, 'B'].fix(0.0) m.flow_in.fix(1.0) return m
def fluidized_create_mdoel(modelparameters): model = po.ConcreteModel() """"defining fixed parameters""" model.biot_number = po.Param(initialize=modelparameters.Bi) model.frequency_factor = po.Param( initialize=modelparameters.frequency_factor) model.activation_energy = po.Param( initialize=modelparameters.activation_energy) model.d_catalyst = po.Param(initialize=modelparameters.d_catalyst) model.product_selectivity = po.Param( initialize=modelparameters.product_selectivity) model.u_super = po.Param(initialize=modelparameters.u_super) model.D_ea = po.Param(initialize=modelparameters.D_ea) model.temperature = po.Param(initialize=modelparameters.Temp) model.intrinsic_rate_constant = po.Param( initialize=modelparameters.frequency_factor * po.exp(-modelparameters.activation_energy / modelparameters.Temp)) #model.a_s = po.Param(initialize = modelparameters.a_s) model.v_frac_aq = po.Param(initialize=modelparameters.v_frac_aq) model.voidage_fluid = po.Param(initialize=modelparameters.voidage_fluid) model.f_b = po.Param(initialize=modelparameters.f_b) model.U_b = po.Param(initialize=modelparameters.U_b) model.solid_density = po.Param(initialize=modelparameters.solid_density) """defining model variables""" model.z = pod.ContinuousSet(bounds=(0, modelparameters.length)) model.global_effectiveness_factor = po.Var(model.z) model.i = po.Set(initialize=["Nitric", "Toluene"]) model.reaction_rate = po.Var(model.z) model.C = po.Var(model.z, model.i) model.P = po.Var(model.z) model.dC_dz = pod.DerivativeVar(model.C, wrt=model.z) model.dP_dz = pod.DerivativeVar(model.P, wrt=model.z) """intial conditions""" model.C[0, "Nitric"].fix(modelparameters.C_B0) model.C[0, "Toluene"].fix(modelparameters.C_A0) model.P[0].fix(0) """def _calculate_intrinsic_rate_constant(m,z): return m.intrinsic_rate_constant[z] == m.frequency_factor * po.exp(-m.activation_energy / m.temperature) model.calculate_intrinsic_rate_constant = po.Constraint(model.z, rule = _calculate_intrinsic_rate_constant)""" def _calcualte_global_effectiveness_factor(m, z): catalyst_rate_constant = m.intrinsic_rate_constant * m.C[z, "Nitric"] thielemodulus = Thiele_Modulus(Diameter_Particle=m.d_catalyst, Intrinsic_Rate=catalyst_rate_constant, D_ea=m.D_ea) effectiveness_factor = po.tanh(thielemodulus) / thielemodulus return m.global_effectiveness_factor[z] == ( (1 / effectiveness_factor) + ((thielemodulus**2) / m.biot_number))**(-1) model.calculate_global_effectiveness_factor = po.Constraint( model.z, rule=_calcualte_global_effectiveness_factor) def _calculate_reaction_rate(m, z): return m.reaction_rate[ z] == m.v_frac_aq * m.global_effectiveness_factor[ z] * m.intrinsic_rate_constant * m.C[z, "Nitric"] * m.C[z, "Toluene"] model.calculate_reaction_rate = po.Constraint( model.z, rule=_calculate_reaction_rate) def _material_balance_reactants(m, z, i): return m.dC_dz[z, i] == ( (1 - m.voidage_fluid) * m.solid_density / (m.f_b * m.U_b)) * (m.reaction_rate[z]) * (m.product_selectivity) model.material_balance_nitric = po.Constraint( model.z, model.i, rule=_material_balance_reactants) def _material_balance_products(m, z): return m.dP_dz[z] == -( (1 - m.voidage_fluid) * m.solid_density / (m.f_b * m.U_b)) * (m.reaction_rate[z]) * (m.product_selectivity) model.material_balance_products = po.Constraint( model.z, rule=_material_balance_products) return model