def run_demo(with_plots=True):
    """
    Static calibration of the quad tank model.
    """

    curr_dir = os.path.dirname(os.path.abspath(__file__))

    jmu_name = compile_jmu("QuadTank_pack.QuadTank_Static", curr_dir + "/files/QuadTank.mop")

    # Load static calibration model
    qt_static = JMUModel(jmu_name)

    # Set control inputs
    qt_static.set("u1", 2.5)
    qt_static.set("u2", 2.5)

    # Save nominal values
    a1_nom = qt_static.get("a1")
    a2_nom = qt_static.get("a2")

    init_res = qt_static.initialize(options={"stat": 1})

    print "Optimal parameter values:"
    print "a1: %2.2e (nominal: %2.2e)" % (qt_static.get("a1"), a1_nom)
    print "a2: %2.2e (nominal: %2.2e)" % (qt_static.get("a2"), a2_nom)

    assert N.abs(qt_static.get("a1") - 7.95797110936e-06) < 1e-3
    assert N.abs(qt_static.get("a2") - 7.73425542448e-06) < 1e-3
def run_demo(with_plots=True):
    """
    Static calibration of the quad tank model.
    """

    curr_dir = os.path.dirname(os.path.abspath(__file__))

    jmu_name = compile_jmu("QuadTank_pack.QuadTank_Static",
                           curr_dir + "/files/QuadTank.mop")

    # Load static calibration model
    qt_static = JMUModel(jmu_name)

    # Set control inputs
    qt_static.set("u1", 2.5)
    qt_static.set("u2", 2.5)

    # Save nominal values
    a1_nom = qt_static.get("a1")
    a2_nom = qt_static.get("a2")

    init_res = qt_static.initialize(options={'stat': 1})

    print "Optimal parameter values:"
    print "a1: %2.2e (nominal: %2.2e)" % (qt_static.get("a1"), a1_nom)
    print "a2: %2.2e (nominal: %2.2e)" % (qt_static.get("a2"), a2_nom)

    assert N.abs(qt_static.get("a1") - 7.95797110936e-06) < 1e-3
    assert N.abs(qt_static.get("a2") - 7.73425542448e-06) < 1e-3
Beispiel #3
0
def run_demo(with_plots=True, with_blocking_factors=False):
    """ 
    Load change of a distillation column. The distillation column model is 
    documented in the paper:

    @Article{hahn+02,
    title={An improved method for nonlinear model reduction using balancing of 
        empirical gramians},
    author={Hahn, J. and Edgar, T.F.},
    journal={Computers and Chemical Engineering},
    volume={26},
    number={10},
    pages={1379-1397},
    year={2002}
    }
    
    Note: This example requires Ipopt with MA27.
    """

    curr_dir = os.path.dirname(os.path.abspath(__file__))

    # Compile the stationary initialization model into a JMU
    jmu_name = compile_jmu("DISTLib.Binary_Dist_initial",
                           curr_dir + "/files/DISTLib.mo")

    # Load a model instance into Python
    init_model = JMUModel(jmu_name)

    # Set inputs for Stationary point A
    rr_0_A = 3.0
    init_model.set('rr', rr_0_A)
    init_result = init_model.initialize()

    # Store stationary point A
    y_A = N.zeros(32)
    x_A = N.zeros(32)
    print(' *** Stationary point A ***')
    print '(Tray index, x_i_A, y_i_A)'
    for i in range(N.size(y_A)):
        y_A[i] = init_model.get('y[' + str(i + 1) + ']')
        x_A[i] = init_model.get('x[' + str(i + 1) + ']')
        print '(' + str(i + 1) + ', %f, %f)' % (x_A[i], y_A[i])

    # Set inputs for stationary point B
    rr_0_B = 2.0
    init_model.set('rr', rr_0_B)
    init_result = init_model.initialize()

    # Store stationary point B
    y_B = N.zeros(32)
    x_B = N.zeros(32)
    print(' *** Stationary point B ***')
    print '(Tray index, x_i_B, y_i_B)'
    for i in range(N.size(y_B)):
        y_B[i] = init_model.get('y[' + str(i + 1) + ']')
        x_B[i] = init_model.get('x[' + str(i + 1) + ']')
        print '(' + str(i + 1) + ', %f, %f)' % (x_B[i], y_B[i])

    # Set up and solve an optimal control problem.

    # Compile the JMU
    jmu_name = compile_jmu(
        "DISTLib_Opt.Binary_Dist_Opt1",
        (curr_dir + "/files/DISTLib.mo", curr_dir + "/files/DISTLib_Opt.mop"),
        compiler_options={'state_start_values_fixed': True})

    # Load the dynamic library and XML data
    model = JMUModel(jmu_name)

    # Initialize the model with parameters

    # Initialize the model to stationary point A
    for i in range(N.size(x_A)):
        model.set('x_0[' + str(i + 1) + ']', x_A[i])

    # Set the target values to stationary point B
    model.set('rr_ref', rr_0_B)
    model.set('y1_ref', y_B[0])

    n_e = 100  # Number of elements
    hs = N.ones(n_e) * 1. / n_e  # Equidistant points
    n_cp = 3
    # Number of collocation points in each element

    # Solve the optimization problem
    if with_blocking_factors:
        # Blocking factors for control parametrization
        blocking_factors = 4 * N.ones(n_e / 4, dtype=N.int)

        opt_opts = model.optimize_options()
        opt_opts['n_e'] = n_e
        opt_opts['n_cp'] = n_cp
        opt_opts['hs'] = hs
        opt_opts['blocking_factors'] = blocking_factors

        opt_res = model.optimize(options=opt_opts)
    else:
        opt_res = model.optimize(options={'n_e': n_e, 'n_cp': n_cp, 'hs': hs})

    # Extract variable profiles
    u1_res = opt_res['rr']
    u1_ref_res = opt_res['rr_ref']
    y1_ref_res = opt_res['y1_ref']
    time = opt_res['time']

    x_res = []
    x_ref_res = []
    for i in range(N.size(x_B)):
        x_res.append(opt_res['x[' + str(i + 1) + ']'])

    y_res = []
    for i in range(N.size(x_B)):
        y_res.append(opt_res['y[' + str(i + 1) + ']'])

    if with_blocking_factors:
        assert N.abs(opt_res.final('cost') / 1.e1 - 2.8549683) < 1e-3
    else:
        assert N.abs(opt_res.final('cost') / 1.e1 - 2.8527469) < 1e-3

    # Plot the results
    if with_plots:
        plt.figure(1)
        plt.clf()
        plt.hold(True)
        plt.subplot(311)
        plt.title('Liquid composition')
        plt.plot(time, x_res[0])
        plt.ylabel('x1')
        plt.grid()
        plt.subplot(312)
        plt.plot(time, x_res[16])
        plt.ylabel('x17')
        plt.grid()
        plt.subplot(313)
        plt.plot(time, x_res[31])
        plt.ylabel('x32')
        plt.grid()
        plt.xlabel('t [s]')
        plt.show()

        # Plot the results
        plt.figure(2)
        plt.clf()
        plt.hold(True)
        plt.subplot(311)
        plt.title('Vapor composition')
        plt.plot(time, y_res[0])
        plt.plot(time, y1_ref_res, '--')
        plt.ylabel('y1')
        plt.grid()
        plt.subplot(312)
        plt.plot(time, y_res[16])
        plt.ylabel('y17')
        plt.grid()
        plt.subplot(313)
        plt.plot(time, y_res[31])
        plt.ylabel('y32')
        plt.grid()
        plt.xlabel('t [s]')
        plt.show()

        plt.figure(3)
        plt.clf()
        plt.hold(True)
        plt.plot(time, u1_res)
        plt.ylabel('u')
        plt.plot(time, u1_ref_res, '--')
        plt.xlabel('t [s]')
        plt.title('Reflux ratio')
        plt.grid()
        plt.show()
Beispiel #4
0
def run_demo(with_plots=True, with_blocking_factors = False):
    """ 
    Load change of a distillation column. The distillation column model is 
    documented in the paper:

    @Article{hahn+02,
    title={An improved method for nonlinear model reduction using balancing of 
        empirical gramians},
    author={Hahn, J. and Edgar, T.F.},
    journal={Computers and Chemical Engineering},
    volume={26},
    number={10},
    pages={1379-1397},
    year={2002}
    }
    
    Note: This example requires Ipopt with MA27.
    """
    
    curr_dir = os.path.dirname(os.path.abspath(__file__));

    # Compile the stationary initialization model into a JMU
    jmu_name = compile_jmu("DISTLib.Binary_Dist_initial", 
        curr_dir+"/files/DISTLib.mo")

    # Load a model instance into Python
    init_model = JMUModel(jmu_name)
    
    # Set inputs for Stationary point A
    rr_0_A = 3.0
    init_model.set('rr',rr_0_A)
    init_result = init_model.initialize()
    
    # Store stationary point A
    y_A = N.zeros(32)
    x_A = N.zeros(32)
    print(' *** Stationary point A ***')
    print '(Tray index, x_i_A, y_i_A)'
    for i in range(N.size(y_A)):
        y_A[i] = init_model.get('y['+ str(i+1) +']')
        x_A[i] = init_model.get('x['+ str(i+1) +']')
        print '(' + str(i+1) + ', %f, %f)' %(x_A[i], y_A[i])
    
    # Set inputs for stationary point B
    rr_0_B = 2.0
    init_model.set('rr',rr_0_B)
    init_result = init_model.initialize()

    # Store stationary point B
    y_B = N.zeros(32)
    x_B = N.zeros(32)
    print(' *** Stationary point B ***')
    print '(Tray index, x_i_B, y_i_B)'
    for i in range(N.size(y_B)):
        y_B[i] = init_model.get('y[' + str(i+1) + ']')
        x_B[i] = init_model.get('x[' + str(i+1) + ']')
        print '(' + str(i+1) + ', %f, %f)' %(x_B[i], y_B[i])

    # Set up and solve an optimal control problem. 

    # Compile the JMU
    jmu_name = compile_jmu("DISTLib_Opt.Binary_Dist_Opt1", 
        (curr_dir+"/files/DISTLib.mo",curr_dir+"/files/DISTLib_Opt.mop"), 
        compiler_options={'state_start_values_fixed':True})

    # Load the dynamic library and XML data
    model = JMUModel(jmu_name)

    # Initialize the model with parameters

    # Initialize the model to stationary point A
    for i in range(N.size(x_A)):
        model.set('x_0[' + str(i+1) + ']', x_A[i])

    # Set the target values to stationary point B
    model.set('rr_ref',rr_0_B)
    model.set('y1_ref',y_B[0])

    n_e = 100               # Number of elements 
    hs = N.ones(n_e)*1./n_e # Equidistant points
    n_cp = 3;               # Number of collocation points in each element

    # Solve the optimization problem
    if with_blocking_factors:
        # Blocking factors for control parametrization
        blocking_factors=4*N.ones(n_e/4,dtype=N.int)
        
        opt_opts = model.optimize_options()
        opt_opts['n_e'] = n_e
        opt_opts['n_cp'] = n_cp
        opt_opts['hs'] = hs
        opt_opts['blocking_factors'] = blocking_factors
        
        opt_res = model.optimize(options=opt_opts)
    else:
        opt_res = model.optimize(options={'n_e':n_e, 'n_cp':n_cp, 'hs':hs})

    # Extract variable profiles
    u1_res     = opt_res['rr']
    u1_ref_res = opt_res['rr_ref']
    y1_ref_res = opt_res['y1_ref']
    time       = opt_res['time']
    
    x_res = []
    x_ref_res = []
    for i in range(N.size(x_B)):
        x_res.append(opt_res['x[' + str(i+1) + ']'])

    y_res = []
    for i in range(N.size(x_B)):
        y_res.append(opt_res['y[' + str(i+1) + ']'])
        
    
    if with_blocking_factors:
        assert N.abs(opt_res.final('cost')/1.e1 - 2.8549683) < 1e-3
    else:
        assert N.abs(opt_res.final('cost')/1.e1 - 2.8527469) < 1e-3

    # Plot the results
    if with_plots:
        plt.figure(1)
        plt.clf()
        plt.hold(True)
        plt.subplot(311)
        plt.title('Liquid composition')
        plt.plot(time, x_res[0])
        plt.ylabel('x1')
        plt.grid()
        plt.subplot(312)
        plt.plot(time, x_res[16])
        plt.ylabel('x17')
        plt.grid()
        plt.subplot(313)
        plt.plot(time, x_res[31])
        plt.ylabel('x32')
        plt.grid()
        plt.xlabel('t [s]')
        plt.show()
        
        # Plot the results
        plt.figure(2)
        plt.clf()
        plt.hold(True)
        plt.subplot(311)
        plt.title('Vapor composition')
        plt.plot(time, y_res[0])
        plt.plot(time, y1_ref_res, '--')
        plt.ylabel('y1')
        plt.grid()
        plt.subplot(312)
        plt.plot(time, y_res[16])
        plt.ylabel('y17')
        plt.grid()
        plt.subplot(313)
        plt.plot(time, y_res[31])
        plt.ylabel('y32')
        plt.grid()
        plt.xlabel('t [s]')
        plt.show()
        
        
        plt.figure(3)
        plt.clf()
        plt.hold(True)
        plt.plot(time, u1_res)
        plt.ylabel('u')
        plt.plot(time, u1_ref_res, '--')
        plt.xlabel('t [s]')
        plt.title('Reflux ratio')
        plt.grid()
        plt.show()
Beispiel #5
0
def run_demo(with_plots=True):
    """
    This example is based on a system composed of two Continously Stirred Tank 
    Reactors (CSTRs) in series. The example demonstrates the following steps:
    
    1. How to solve a DAE initialization problem. The initialization model have 
       equations specifying that all derivatives should be identically zero, 
       which implies that a stationary solution is obtained. Two stationary 
       points, corresponding to different inputs, are computed. We call the 
       stationary points A and B respectively. For more information about the 
       DAE initialization algorithm, see http://www.jmodelica.org/page/10.
    
    2. An optimal control problem is solved where the objective is to transfer 
       the state of the system from stationary point A to point B. Here, it is 
       also demonstrated how to set parameter values in a model. More 
       information about the simultaneous optimization algorithm can be found at 
       http://www.jmodelica.org/page/10.
    
    3. The optimization result is saved to file and then the important variables 
       are plotted.
    """
    
    curr_dir = os.path.dirname(os.path.abspath(__file__));
    
    # Compile the stationary initialization model into a DLL
    jmu_name = compile_jmu("CSTRLib.Components.Two_CSTRs_stat_init", 
        os.path.join(curr_dir, "files", "CSTRLib.mo"))

    # Load a JMU model instance
    init_model = JMUModel(jmu_name)
    
    # Set inputs for Stationary point A
    u1_0_A = 1
    u2_0_A = 1
    init_model.set('u1',u1_0_A)
    init_model.set('u2',u2_0_A)
    
    # Solve the DAE initialization system with Ipopt
    init_result = init_model.initialize()
    
    # Store stationary point A
    CA1_0_A = init_model.get('CA1')
    CA2_0_A = init_model.get('CA2')
    T1_0_A = init_model.get('T1')
    T2_0_A = init_model.get('T2')
    
    # Print some data for stationary point A
    print(' *** Stationary point A ***')
    print('u = [%f,%f]' % (u1_0_A,u2_0_A))
    print('CAi = [%f,%f]' % (CA1_0_A,CA2_0_A))
    print('Ti = [%f,%f]' % (T1_0_A,T2_0_A))
    
    # Set inputs for stationary point B
    u1_0_B = 1.1
    u2_0_B = 0.9
    init_model.set('u1',u1_0_B)
    init_model.set('u2',u2_0_B)
    
    # Solve the DAE initialization system with Ipopt
    init_result = init_model.initialize()
   
    # Stationary point B
    CA1_0_B = init_model.get('CA1')
    CA2_0_B = init_model.get('CA2')
    T1_0_B = init_model.get('T1')
    T2_0_B = init_model.get('T2')

    # Print some data for stationary point B
    print(' *** Stationary point B ***')
    print('u = [%f,%f]' % (u1_0_B,u2_0_B))
    print('CAi = [%f,%f]' % (CA1_0_B,CA2_0_B))
    print('Ti = [%f,%f]' % (T1_0_B,T2_0_B))
    
    ## Set up and solve an optimal control problem. 

    # Compile the Model
    jmu_name = compile_jmu("CSTR2_Opt", 
        [os.path.join(curr_dir, "files", "CSTRLib.mo"), os.path.join(curr_dir, "files", "CSTR2_Opt.mop")],
        compiler_options={'enable_variable_scaling':True, 'index_reduction':True})

    # Load the dynamic library and XML data
    model = JMUModel(jmu_name)

    # Initialize the model with parameters

    # Initialize the model to stationary point A
    model.set('cstr.two_CSTRs_Series.CA1_0',CA1_0_A)
    model.set('cstr.two_CSTRs_Series.CA2_0',CA2_0_A)
    model.set('cstr.two_CSTRs_Series.T1_0',T1_0_A)
    model.set('cstr.two_CSTRs_Series.T2_0',T2_0_A)
    
    # Set the target values to stationary point B
    model.set('u1_ref',u1_0_B)
    model.set('u2_ref',u2_0_B)
    model.set('CA1_ref',CA1_0_B)
    model.set('CA2_ref',CA2_0_B)
    
    # Initialize the optimization mesh
    n_e = 50                 # Number of elements 
    hs = N.ones(n_e)*1./n_e  # Equidistant points
    n_cp = 3;                # Number of collocation points in each element
    
    res = model.optimize(
        options={'n_e':n_e, 'hs':hs, 'n_cp':n_cp, 
            'blocking_factors':2*N.ones(n_e/2,dtype=N.int), 
            'IPOPT_options':{'tol':1e-4}})
        
    # Extract variable profiles
    CA1_res=res['cstr.two_CSTRs_Series.CA1']
    CA2_res=res['cstr.two_CSTRs_Series.CA2']
    T1_res=res['cstr.two_CSTRs_Series.T1']
    T2_res=res['cstr.two_CSTRs_Series.T2']
    u1_res=res['cstr.two_CSTRs_Series.u1']
    u2_res=res['cstr.two_CSTRs_Series.u2']
    der_u2_res=res['der_u2']
    
    CA1_ref_res=res['CA1_ref']
    CA2_ref_res=res['CA2_ref']
    
    u1_ref_res=res['u1_ref']
    u2_ref_res=res['u2_ref']
    
    cost=res['cost']
    time=res['time']

    assert N.abs(res.final('cost') - 1.4745648e+01) < 1e-3
    
    # Plot the results
    if with_plots:
        plt.figure(1)
        plt.clf()
        plt.hold(True)
        plt.subplot(211)
        plt.plot(time,CA1_res)
        plt.plot([time[0],time[-1]],[CA1_ref_res, CA1_ref_res],'--')
        plt.ylabel('Concentration reactor 1 [J/l]')
        plt.grid()
        plt.subplot(212)
        plt.plot(time,CA2_res)
        plt.plot([time[0],time[-1]],[CA2_ref_res, CA2_ref_res],'--')
        plt.ylabel('Concentration reactor 2 [J/l]')
        plt.xlabel('t [s]')
        plt.grid()
        plt.show()
        
        plt.figure(2)
        plt.clf()
        plt.hold(True)
        plt.subplot(211)
        plt.plot(time,T1_res)
        plt.ylabel('Temperature reactor 1 [K]')
        plt.grid()
        plt.subplot(212)
        plt.plot(time,T2_res)
        plt.ylabel('Temperature reactor 2 [K]')
        plt.grid()
        plt.xlabel('t [s]')
        plt.show()
        
        plt.figure(3)
        plt.clf()
        plt.hold(True)
        plt.subplot(211)
        plt.plot(time,u2_res)
        plt.ylabel('Input 2')
        plt.plot([time[0],time[-1]],[u2_ref_res, u2_ref_res],'--')
        plt.grid()
        plt.subplot(212)
        plt.plot(time,der_u2_res)
        plt.ylabel('Derivative of input 2')
        plt.xlabel('t [s]')
        plt.grid()
        plt.show()
Beispiel #6
0
def run_demo(with_plots=True):
    """
    This example is based on a system composed of two Continously Stirred Tank 
    Reactors (CSTRs) in series. The example demonstrates the following steps:
    
    1. How to solve a DAE initialization problem. The initialization model have 
       equations specifying that all derivatives should be identically zero, 
       which implies that a stationary solution is obtained. Two stationary 
       points, corresponding to different inputs, are computed. We call the 
       stationary points A and B respectively. For more information about the 
       DAE initialization algorithm, see http://www.jmodelica.org/page/10.
    
    2. An optimal control problem is solved where the objective is to transfer 
       the state of the system from stationary point A to point B. Here, it is 
       also demonstrated how to set parameter values in a model. More 
       information about the simultaneous optimization algorithm can be found at 
       http://www.jmodelica.org/page/10.
    
    3. The optimization result is saved to file and then the important variables 
       are plotted.
    """

    curr_dir = os.path.dirname(os.path.abspath(__file__))

    # Compile the stationary initialization model into a DLL
    jmu_name = compile_jmu("CSTRLib.Components.Two_CSTRs_stat_init",
                           os.path.join(curr_dir, "files", "CSTRLib.mo"))

    # Load a JMU model instance
    init_model = JMUModel(jmu_name)

    # Set inputs for Stationary point A
    u1_0_A = 1
    u2_0_A = 1
    init_model.set('u1', u1_0_A)
    init_model.set('u2', u2_0_A)

    # Solve the DAE initialization system with Ipopt
    init_result = init_model.initialize()

    # Store stationary point A
    CA1_0_A = init_model.get('CA1')
    CA2_0_A = init_model.get('CA2')
    T1_0_A = init_model.get('T1')
    T2_0_A = init_model.get('T2')

    # Print some data for stationary point A
    print(' *** Stationary point A ***')
    print('u = [%f,%f]' % (u1_0_A, u2_0_A))
    print('CAi = [%f,%f]' % (CA1_0_A, CA2_0_A))
    print('Ti = [%f,%f]' % (T1_0_A, T2_0_A))

    # Set inputs for stationary point B
    u1_0_B = 1.1
    u2_0_B = 0.9
    init_model.set('u1', u1_0_B)
    init_model.set('u2', u2_0_B)

    # Solve the DAE initialization system with Ipopt
    init_result = init_model.initialize()

    # Stationary point B
    CA1_0_B = init_model.get('CA1')
    CA2_0_B = init_model.get('CA2')
    T1_0_B = init_model.get('T1')
    T2_0_B = init_model.get('T2')

    # Print some data for stationary point B
    print(' *** Stationary point B ***')
    print('u = [%f,%f]' % (u1_0_B, u2_0_B))
    print('CAi = [%f,%f]' % (CA1_0_B, CA2_0_B))
    print('Ti = [%f,%f]' % (T1_0_B, T2_0_B))

    ## Set up and solve an optimal control problem.

    # Compile the Model
    jmu_name = compile_jmu("CSTR2_Opt", [
        os.path.join(curr_dir, "files", "CSTRLib.mo"),
        os.path.join(curr_dir, "files", "CSTR2_Opt.mop")
    ],
                           compiler_options={
                               'enable_variable_scaling': True,
                               'index_reduction': True
                           })

    # Load the dynamic library and XML data
    model = JMUModel(jmu_name)

    # Initialize the model with parameters

    # Initialize the model to stationary point A
    model.set('cstr.two_CSTRs_Series.CA1_0', CA1_0_A)
    model.set('cstr.two_CSTRs_Series.CA2_0', CA2_0_A)
    model.set('cstr.two_CSTRs_Series.T1_0', T1_0_A)
    model.set('cstr.two_CSTRs_Series.T2_0', T2_0_A)

    # Set the target values to stationary point B
    model.set('u1_ref', u1_0_B)
    model.set('u2_ref', u2_0_B)
    model.set('CA1_ref', CA1_0_B)
    model.set('CA2_ref', CA2_0_B)

    # Initialize the optimization mesh
    n_e = 50  # Number of elements
    hs = N.ones(n_e) * 1. / n_e  # Equidistant points
    n_cp = 3
    # Number of collocation points in each element

    res = model.optimize(
        options={
            'n_e': n_e,
            'hs': hs,
            'n_cp': n_cp,
            'blocking_factors': 2 * N.ones(n_e / 2, dtype=N.int),
            'IPOPT_options': {
                'tol': 1e-4
            }
        })

    # Extract variable profiles
    CA1_res = res['cstr.two_CSTRs_Series.CA1']
    CA2_res = res['cstr.two_CSTRs_Series.CA2']
    T1_res = res['cstr.two_CSTRs_Series.T1']
    T2_res = res['cstr.two_CSTRs_Series.T2']
    u1_res = res['cstr.two_CSTRs_Series.u1']
    u2_res = res['cstr.two_CSTRs_Series.u2']
    der_u2_res = res['der_u2']

    CA1_ref_res = res['CA1_ref']
    CA2_ref_res = res['CA2_ref']

    u1_ref_res = res['u1_ref']
    u2_ref_res = res['u2_ref']

    cost = res['cost']
    time = res['time']

    assert N.abs(res.final('cost') - 1.4745648e+01) < 1e-3

    # Plot the results
    if with_plots:
        plt.figure(1)
        plt.clf()
        plt.hold(True)
        plt.subplot(211)
        plt.plot(time, CA1_res)
        plt.plot([time[0], time[-1]], [CA1_ref_res, CA1_ref_res], '--')
        plt.ylabel('Concentration reactor 1 [J/l]')
        plt.grid()
        plt.subplot(212)
        plt.plot(time, CA2_res)
        plt.plot([time[0], time[-1]], [CA2_ref_res, CA2_ref_res], '--')
        plt.ylabel('Concentration reactor 2 [J/l]')
        plt.xlabel('t [s]')
        plt.grid()
        plt.show()

        plt.figure(2)
        plt.clf()
        plt.hold(True)
        plt.subplot(211)
        plt.plot(time, T1_res)
        plt.ylabel('Temperature reactor 1 [K]')
        plt.grid()
        plt.subplot(212)
        plt.plot(time, T2_res)
        plt.ylabel('Temperature reactor 2 [K]')
        plt.grid()
        plt.xlabel('t [s]')
        plt.show()

        plt.figure(3)
        plt.clf()
        plt.hold(True)
        plt.subplot(211)
        plt.plot(time, u2_res)
        plt.ylabel('Input 2')
        plt.plot([time[0], time[-1]], [u2_ref_res, u2_ref_res], '--')
        plt.grid()
        plt.subplot(212)
        plt.plot(time, der_u2_res)
        plt.ylabel('Derivative of input 2')
        plt.xlabel('t [s]')
        plt.grid()
        plt.show()