def test_initialize(): '''Very rough test, just to make sure degrees of freedom are not violated. ''' mod = make_model(horizon=2, ntfe=20, ntcp=1, inlet_E=11.91, inlet_S=12.92) assert degrees_of_freedom(mod) == 0 originally_active = ComponentMap([ (comp, comp.active) for comp in mod.component_data_objects((Block, Constraint)) ]) originally_fixed = ComponentMap([ (var, var.fixed) for var in mod.component_data_objects(Var) ]) initialize_by_time_element(mod.fs, mod.fs.time, solver=solver, outlvl=idaeslog.DEBUG, fix_diff_only=False) assert degrees_of_freedom(mod) == 0 for comp in mod.component_data_objects((Block, Constraint)): assert comp.active == originally_active[comp] for var in mod.component_data_objects(Var): assert var.fixed == originally_fixed[var]
def test_initialize(self, iron_oc): optarg = { "bound_push": 1e-8, 'halt_on_ampl_error': 'yes', 'linear_solver': 'ma27' } initialization_tester(iron_oc) solver = get_solver('ipopt', optarg) # create solver initialize_by_time_element(iron_oc.fs, iron_oc.fs.time, solver=solver)
def test_initialize_by_time_element(): horizon = 6 time_set = [0, horizon] ntfe = 60 # For a finite element every six seconds ntcp = 2 m = ConcreteModel(name='CSTR model for testing') m.fs = FlowsheetBlock(default={ 'dynamic': True, 'time_set': time_set, 'time_units': pyunits.minute }) m.fs.properties = AqueousEnzymeParameterBlock() m.fs.reactions = EnzymeReactionParameterBlock( default={'property_package': m.fs.properties}) m.fs.cstr = CSTR( default={ "property_package": m.fs.properties, "reaction_package": m.fs.reactions, "material_balance_type": MaterialBalanceType.componentTotal, "energy_balance_type": EnergyBalanceType.enthalpyTotal, "momentum_balance_type": MomentumBalanceType.none, "has_heat_of_reaction": True }) # Time discretization disc = TransformationFactory('dae.collocation') disc.apply_to(m, wrt=m.fs.time, nfe=ntfe, ncp=ntcp, scheme='LAGRANGE-RADAU') # Fix geometry variables m.fs.cstr.volume[0].fix(1.0) # Fix initial conditions: for p, j in m.fs.properties.phase_list * m.fs.properties.component_list: if j == 'Solvent': continue m.fs.cstr.control_volume.material_holdup[0, p, j].fix(0) # Fix inlet conditions # This is a huge hack because I didn't know that the proper way to # have multiple inlets to a CSTR was to use a mixer. # I 'combine' both my inlet streams before sending them to the CSTR. for t, j in m.fs.time * m.fs.properties.component_list: if t <= 2: if j == 'E': m.fs.cstr.inlet.conc_mol[t, j].fix(11.91 * 0.1 / 2.2) elif j == 'S': m.fs.cstr.inlet.conc_mol[t, j].fix(12.92 * 2.1 / 2.2) elif j != 'Solvent': m.fs.cstr.inlet.conc_mol[t, j].fix(0) elif t <= 4: if j == 'E': m.fs.cstr.inlet.conc_mol[t, j].fix(5.95 * 0.1 / 2.2) elif j == 'S': m.fs.cstr.inlet.conc_mol[t, j].fix(12.92 * 2.1 / 2.2) elif j != 'Solvent': m.fs.cstr.inlet.conc_mol[t, j].fix(0) else: if j == 'E': m.fs.cstr.inlet.conc_mol[t, j].fix(8.95 * 0.1 / 2.2) elif j == 'S': m.fs.cstr.inlet.conc_mol[t, j].fix(16.75 * 2.1 / 2.2) elif j != 'Solvent': m.fs.cstr.inlet.conc_mol[t, j].fix(0) m.fs.cstr.inlet.conc_mol[:, 'Solvent'].fix(1.) m.fs.cstr.inlet.flow_vol.fix(2.2) m.fs.cstr.inlet.temperature.fix(300) # Fix outlet conditions m.fs.cstr.outlet.flow_vol.fix(2.2) m.fs.cstr.outlet.temperature[m.fs.time.first()].fix(300) assert degrees_of_freedom(m) == 0 initialize_by_time_element(m.fs, m.fs.time, solver=solver) assert degrees_of_freedom(m) == 0 # Assert that the result looks how we expect assert m.fs.cstr.outlet.conc_mol[0, 'S'].value == 0 assert abs(m.fs.cstr.outlet.conc_mol[2, 'S'].value - 11.389) < 1e-2 assert abs(m.fs.cstr.outlet.conc_mol[4, 'P'].value - 0.2191) < 1e-3 assert abs(m.fs.cstr.outlet.conc_mol[6, 'E'].value - 0.0327) < 1e-3 assert abs(m.fs.cstr.outlet.temperature[6].value - 289.7) < 1 # Assert that model is still fixed and deactivated as expected assert (m.fs.cstr.control_volume.material_holdup[m.fs.time.first(), 'aq', 'S'].fixed) for t in m.fs.time: if t != m.fs.time.first(): assert (not m.fs.cstr.control_volume.material_holdup[t, 'aq', 'S'].fixed) assert not m.fs.cstr.outlet.temperature[t].fixed assert ( m.fs.cstr.control_volume.material_holdup_calculation[t, 'aq', 'C'].active) assert m.fs.cstr.control_volume.properties_out[t].active assert not m.fs.cstr.outlet.conc_mol[t, 'S'].fixed assert m.fs.cstr.inlet.conc_mol[t, 'S'].fixed # Assert that constraints are feasible after initialization for con in m.fs.component_data_objects(Constraint, active=True): assert value(con.body) - value(con.upper) < 1e-5 assert value(con.lower) - value(con.body) < 1e-5 results = solver.solve(m.fs) assert check_optimal_termination(results)
def main(m): m.fs = FlowsheetBlock(default={"dynamic": True, "time_set": [0, 3600], "time_units": pyunits.s}) m.fs.gas_props = GasPhaseParameterBlock() m.fs.solid_props = SolidPhaseParameterBlock() m.fs.solid_rxns = HeteroReactionParameterBlock( default={"solid_property_package": m.fs.solid_props, "gas_property_package": m.fs.gas_props}) m.fs.TGA = FixedBed0D(default={ "energy_balance_type": EnergyBalanceType.none, "gas_property_package": m.fs.gas_props, "solid_property_package": m.fs.solid_props, "reaction_package": m.fs.solid_rxns}) # Discretize time domain m.discretizer = TransformationFactory('dae.finite_difference') m.discretizer.apply_to(m, nfe=100, wrt=m.fs.time, scheme="BACKWARD") # Set reactor design conditions m.fs.TGA.bed_diameter.fix(1) # diameter of the TGA reactor [m] m.fs.TGA.bed_height.fix(1) # height of solids in the TGA reactor [m] # Set initial conditions of the solid phase m.fs.TGA.solids[0].particle_porosity.fix(0.20) m.fs.TGA.solids[0].mass_frac_comp['Fe2O3'].fix(0.45) m.fs.TGA.solids[0].mass_frac_comp['Fe3O4'].fix(0) m.fs.TGA.solids[0].mass_frac_comp['Al2O3'].fix(0.55) m.fs.TGA.solids[0].temperature.fix(1273.15) # Set conditions of the gas phase (this is all fixed as gas side assumption # is excess gas flowrate which means all state variables remain unchanged) for t in m.fs.time: m.fs.TGA.gas[t].temperature.fix(1273.15) m.fs.TGA.gas[t].pressure.fix(1.01325E5) # 1atm m.fs.TGA.gas[t].mole_frac_comp['CO2'].fix(0.4) m.fs.TGA.gas[t].mole_frac_comp['H2O'].fix(0.5) m.fs.TGA.gas[t].mole_frac_comp['CH4'].fix(0.1) # Solver options optarg = { "bound_push": 1e-8, 'halt_on_ampl_error': 'yes', 'linear_solver': 'ma27' } t_start = time.time() # Run start time m.fs.TGA.initialize() t_initialize = time.time() # Initialization time solver = get_solver('ipopt', optarg) # create solver initialize_by_time_element(m.fs, m.fs.time, solver=solver) solver.solve(m, tee=True) t_simulation = time.time() # Simulation time print("\n") print("----------------------------------------------------------") print('Total initialization time: ', value(t_initialize - t_start), " s") print("----------------------------------------------------------") print("\n") print("----------------------------------------------------------") print('Total simulation time: ', value(t_simulation - t_start), " s") print("----------------------------------------------------------") return m