def run_demo(with_plots=True):
    """
    Demonstrate how to solve a minimum time dynamic optimization problem based 
    on a Van der Pol oscillator system.
    """

    file_paths = (os.path.join(get_files_path(), "JMExamples_opt.mop"),
                  os.path.join(get_files_path(), "JMExamples.mo"))
    vdp = transfer_optimization_problem("JMExamples_opt.VDP_Opt_Min_Time", file_paths)
    res = vdp.optimize()
    
    # Extract variable profiles
    x1=res['x1']
    x2=res['x2']
    u=res['u']
    t=res['time']

    assert N.abs(res.final('finalTime') - 2.2811587) < 1e-3

    if with_plots:
        # Plot
        plt.figure(1)
        plt.clf()
        plt.subplot(311)
        plt.plot(t,x1)
        plt.grid()
        plt.ylabel('x1')
        
        plt.subplot(312)
        plt.plot(t,x2)
        plt.grid()
        plt.ylabel('x2')
        
        plt.subplot(313)
        plt.plot(t,u,'x-')
        plt.grid()
        plt.ylabel('u')
        plt.xlabel('time')
        plt.show()
Example #2
0
def run_demo(with_plots=True):
    """
    Demonstrate how to optimize a VDP oscillator using CasADiInterface.
    """
    # Compile and load optimization problem
    from pyjmi import get_files_path, transfer_to_casadi_interface
    file_path = os.path.join(get_files_path(), "VDP.mop")
    op = transfer_to_casadi_interface("VDP_pack.VDP_Opt2", file_path)
    
    # Set algorithm options
    opts = op.optimize_options()
    opts['n_e'] = 30
    
    # Optimize
    res = op.optimize(options=opts)
    
    # Extract variable profiles
    x1 = res['x1']
    x2 = res['x2']
    u = res['u']
    time = res['time']
    
    assert N.abs(res.final('x1')) < 1e-3
    assert N.abs(res.final('x2')) < 1e-3
    
    # Plot
    if with_plots:
        plt.figure(1)
        plt.clf()
        plt.subplot(3, 1, 1)
        plt.plot(time, x1)
        plt.grid()
        plt.ylabel('x1')
        
        plt.subplot(3, 1, 2)
        plt.plot(time, x2)
        plt.grid()
        plt.ylabel('x2')
        
        plt.subplot(3, 1, 3)
        plt.plot(time, u)
        plt.grid()
        plt.ylabel('u')
        plt.xlabel('time')
        plt.show()
Example #3
0
def run_demo(with_plots=True):
    n_e = 20
    delay_n_e = 5
    horizon = 1.0
    delay = horizon * delay_n_e / n_e

    # Compile and load optimization problem
    file_path = os.path.join(get_files_path(), "DelayedFeedbackOpt.mop")
    opt = transfer_optimization_problem("DelayTest", file_path)

    # Set value for u2(t) when t < delay
    opt.getVariable('u2').setAttribute('initialGuess', 0.25)

    # Set algorithm options
    opts = opt.optimize_options()
    opts['n_e'] = n_e
    # Set delayed feedback from u1 to u2
    opts['delayed_feedback'] = {'u2': ('u1', delay_n_e)}

    # Optimize
    res = opt.optimize(options=opts)

    # Extract variable profiles
    x_res = res['x']
    u1_res = res['u1']
    u2_res = res['u2']
    time_res = res['time']

    # Plot results
    if with_plots:
        plt.plot(time_res, x_res, time_res, u1_res, time_res, u2_res)
        plt.hold(True)
        plt.plot(time_res + delay, u1_res, '--')
        plt.hold(False)
        plt.legend(('x', 'u1', 'u2', 'delay(u1)'))

        plt.show()
Example #4
0
def run_demo(with_plots=True):
    """
    This example is based on the Hicks-Ray Continuously Stirred Tank Reactors 
    (CSTR) system. The system has two states, the concentration and the 
    temperature. The control input to the system is the temperature of the 
    cooling flow in the reactor jacket. The chemical reaction in the reactor is 
    exothermic, and also temperature dependent; high temperature results in high 
    reaction rate.
    
    The problem is solved using the CasADi-based collocation algorithm. The
    steps performed correspond to those demonstrated in
    example pyjmi.examples.cstr, where the same problem is solved using the
    default JMI algorithm. FMI is used for initialization and simulation
    purposes.
    
    The following steps are demonstrated in this example:
    
    1.  How to solve the initialization problem. The initialization model has
        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. Point A corresponds to
        operating conditions where the reactor is cold and the reaction rate is
        low, whereas point B corresponds to a higher temperature where the
        reaction rate is high.
    
    2.  How to generate an initial guess for a direct collocation method by
        means of simulation with a constant input. The trajectories resulting
        from the simulation are used to initialize the variables in the
        transcribed NLP.
       
    3.  An optimal control problem is solved where the objective is to transfer 
        the state of the system from stationary point A to point B. The
        challenge is to ignite the reactor while avoiding uncontrolled
        temperature increase.

    4.  Finally the system is simulated using the optimal control profile. This
        step is important in order to verify that the approximation in the
        transcription step is sufficiently accurate.
    """
    ### 1. Solve the initialization problem
    # Locate the Modelica and Optimica code
    file_path = os.path.join(get_files_path(), "CSTR.mop")

    # Compile the stationary initialization model into a FMU
    init_fmu = compile_fmu("CSTR.CSTR_Init", file_path)

    # Load the FMU
    init_model = load_fmu(init_fmu)

    # Set input for Stationary point A
    Tc_0_A = 250
    init_model.set('Tc', Tc_0_A)

    # Solve the initialization problem using FMI
    init_model.initialize()

    # Store stationary point A
    [c_0_A, T_0_A] = init_model.get(['c', 'T'])

    # Print some data for stationary point A
    print(' *** Stationary point A ***')
    print('Tc = %f' % Tc_0_A)
    print('c = %f' % c_0_A)
    print('T = %f' % T_0_A)

    # Set inputs for Stationary point B
    init_model = load_fmu(init_fmu)
    Tc_0_B = 280
    init_model.set('Tc', Tc_0_B)

    # Solve the initialization problem using FMI
    init_model.initialize()

    # Store stationary point B
    [c_0_B, T_0_B] = init_model.get(['c', 'T'])

    # Print some data for stationary point B
    print(' *** Stationary point B ***')
    print('Tc = %f' % Tc_0_B)
    print('c = %f' % c_0_B)
    print('T = %f' % T_0_B)

    ### 2. Compute initial guess trajectories by means of simulation
    # Compile the optimization initialization model
    init_sim_fmu = compile_fmu("CSTR.CSTR_Init_Optimization", file_path)

    # Load the model
    init_sim_model = load_fmu(init_sim_fmu)

    # Set initial and reference values
    init_sim_model.set('cstr.c_init', c_0_A)
    init_sim_model.set('cstr.T_init', T_0_A)
    init_sim_model.set('c_ref', c_0_B)
    init_sim_model.set('T_ref', T_0_B)
    init_sim_model.set('Tc_ref', Tc_0_B)

    # Simulate with constant input Tc
    init_res = init_sim_model.simulate(start_time=0., final_time=150.)

    # Extract variable profiles
    c_init_sim = init_res['cstr.c']
    T_init_sim = init_res['cstr.T']
    Tc_init_sim = init_res['cstr.Tc']
    t_init_sim = init_res['time']

    # Plot the initial guess trajectories
    if with_plots:
        plt.close(1)
        plt.figure(1)
        plt.hold(True)
        plt.subplot(3, 1, 1)
        plt.plot(t_init_sim, c_init_sim)
        plt.grid()
        plt.ylabel('Concentration')
        plt.title('Initial guess obtained by simulation')

        plt.subplot(3, 1, 2)
        plt.plot(t_init_sim, T_init_sim)
        plt.grid()
        plt.ylabel('Temperature')

        plt.subplot(3, 1, 3)
        plt.plot(t_init_sim, Tc_init_sim)
        plt.grid()
        plt.ylabel('Cooling temperature')
        plt.xlabel('time')
        plt.show()

    ### 3. Solve the optimal control problem
    # Compile model
    fmux = compile_fmux("CSTR.CSTR_Opt2", file_path)

    # Load model
    cstr = CasadiModel(fmux)

    # Set reference values
    cstr.set('Tc_ref', Tc_0_B)
    cstr.set('c_ref', c_0_B)
    cstr.set('T_ref', T_0_B)

    # Set initial values
    cstr.set('cstr.c_init', c_0_A)
    cstr.set('cstr.T_init', T_0_A)

    # Set options
    opt_opts = cstr.optimize_options()
    opt_opts['n_e'] = 100  # Number of elements
    opt_opts['init_traj'] = init_res.result_data

    # Solve the optimal control problem
    res = cstr.optimize(options=opt_opts)

    # Extract variable profiles
    c_res = res['cstr.c']
    T_res = res['cstr.T']
    Tc_res = res['cstr.Tc']
    time_res = res['time']

    c_ref = res['c_ref']
    T_ref = res['T_ref']
    Tc_ref = res['Tc_ref']

    # Verify solution for testing purposes
    try:
        import casadi
    except:
        pass
    else:
        cost = float(res.solver.solver.output(casadi.NLP_SOLVER_F))
        assert (N.abs(cost / 1.e3 - 1.8585429) < 1e-3)

    # Plot the results
    if with_plots:
        plt.close(2)
        plt.figure(2)
        plt.hold(True)
        plt.subplot(3, 1, 1)
        plt.plot(time_res, c_res)
        plt.plot([time_res[0], time_res[-1]], [c_ref, c_ref], '--')
        plt.grid()
        plt.ylabel('Concentration')
        plt.title('Optimized trajectories')

        plt.subplot(312)
        plt.plot(time_res, T_res)
        plt.plot([time_res[0], time_res[-1]], [T_ref, T_ref], '--')
        plt.grid()
        plt.ylabel('Temperature')

        plt.subplot(313)
        plt.plot(time_res, Tc_res)
        plt.plot([time_res[0], time_res[-1]], [Tc_ref, Tc_ref], '--')
        plt.grid()
        plt.ylabel('Cooling temperature')
        plt.xlabel('time')
        plt.show()

    ### 4. Simulate to verify the optimal solution
    # Compile model
    sim_fmu = compile_fmu("CSTR.CSTR", file_path)

    # Load model
    sim_model = load_fmu(sim_fmu)

    # Get optimized input
    (_, opt_input) = res.solver.get_opt_input()

    # Set initial values
    sim_model.set('c_init', c_0_A)
    sim_model.set('T_init', T_0_A)

    # Simulate using optimized input
    res = sim_model.simulate(start_time=0.,
                             final_time=150.,
                             input=('Tc', opt_input))

    # Extract variable profiles
    c_sim = res['c']
    T_sim = res['T']
    Tc_sim = res['Tc']
    time_sim = res['time']

    # Plot the results
    if with_plots:
        plt.close(3)
        plt.figure(3)
        plt.hold(True)
        plt.subplot(3, 1, 1)
        plt.plot(time_res, c_res, '--', lw=5)
        plt.plot(time_sim, c_sim, lw=2)
        plt.legend(('optimized', 'simulated'))
        plt.grid(True)
        plt.ylabel('Concentration')
        plt.title('Verification')

        plt.subplot(3, 1, 2)
        plt.plot(time_res, T_res, '--', lw=5)
        plt.plot(time_sim, T_sim, lw=2)
        plt.grid(True)
        plt.ylabel('Temperature')

        plt.subplot(3, 1, 3)
        plt.plot(time_res, Tc_res, '--', lw=5)
        plt.plot(time_sim, Tc_sim, lw=2)
        plt.grid(True)
        plt.ylabel('Cooling temperature')
        plt.xlabel('time')
        plt.show()
def run_demo():
    """
    
    """
    # Locate the model and file paths 
    file_path = os.path.join(get_files_path(), "DrumBoiler.mop")
    model_name = "DrumBoilerpackage.DrumBoiler"

    # Load measurement data
    RCdata = get_test_data()
    measurements = RCdata['measurements'] 
    time = RCdata['time']
    # Extract control signal data from measurements
    inputs={}
    inputs['uc']= measurements.pop('uc')
    inputs['fc']= measurements.pop('fc')

    # Transfer model to Casadi interface
    op = transfer_optimization_problem(model_name, file_path, accept_model = True)
    op_opts = op.optimize_options()

    # Create greybox object
    GB = GreyBox(op, op_opts, measurements, inputs, time)

    # Set some variable attributes
    GB.set_variable_attribute(GB.get_noise_covariance_variable('E'), 'max', 100)
    GB.set_variable_attribute(GB.get_noise_covariance_variable('P'), 'max', 100)
    GB.set_variable_attribute('x10', 'initialGuess', 148)
    GB.set_variable_attribute('x20', 'initialGuess', 27.5)
    
    # Define null model free parameters and other parameters to free
    nullModelFree = set(['GreyBox_r_E', 'GreyBox_r_P', 'x10', 'x20'])
    optimizeParameters = set(["TD","TR","A4","distE","distP"])
    
       # Define null model free parameters and other parameters to free
    nullModelFree = set(['GreyBox_r_E', 'GreyBox_r_P', 'x10', 'x20'])
    
    # Optimize null model
    identification = GB.identify(nullModelFree)
    

    # Create dictionaries for results
    testcases = []
    
    for var in optimizeParameters:
        # Add var to set of free parameters
        testcases.append(identification.release([var]))
    
    print("=======================SUMMARY========================")

    results = identification.compare(testcases)

    # reference data
    nullModelReferenceCost = 5631.068823 #the cost from the null model
    reference = {'TD':{'cost':5466.596971, 'costred':164.471852, 'risk':0.000000},'TR':{'cost':5629.636935, 'costred':1.431888, 'risk':0.731872},'A4':{'cost':5630.900339, 'costred':0.168484, 'risk':0.996721}
                ,'distE':{'cost':4362.561987, 'costred':1268.506836, 'risk':0.000000},'distP':{'cost':4399.728897, 'costred':1231.339926, 'risk':0.000000}} #Create reference by running without framework
    tol = 1e-3
      
    # Assert nullmodel 
    assert(N.abs(identification.cost - nullModelReferenceCost) < tol)
    
    # Assert results  
    for i, var in enumerate(optimizeParameters):
        assert(N.abs(results[i]['cost'] - reference[var]['cost']) < tol)
        assert(N.abs(results[i]['costred'] - reference[var]['costred']) < tol)
        assert(N.abs(results[i]['risk'] - reference[var]['risk']) < tol)
Example #6
0
def run_demo(with_plots=True):
    """
    This example is based on the Hicks-Ray Continuously Stirred Tank Reactors 
    (CSTR) system. The system has two states, the concentration and the 
    temperature. The control input to the system is the temperature of the 
    cooling flow in the reactor jacket. The chemical reaction in the reactor is 
    exothermic, and also temperature dependent; high temperature results in 
    high reaction rate.

    The problem is solved using the CasADi-based collocation algorithm through 
    the MPC-class. FMI is used for initialization and simulation purposes.

    The following steps are demonstrated in this example:

    1.  How to generate an initial guess for a direct collocation method by
        means of simulation with a constant input. The trajectories resulting
        from the simulation are used to initialize the variables in the
        transcribed NLP, in the first sample(optimization).

    2.  An optimal control problem is defined where the objective is to 
        transfer the state of the system from stationary point A to point B. 
        An MPC object for the optimization problem is created. After each 
        sample the NLP is updated with an estimate of the states in the next 
        sample. The estimate is done by simulating the model for one sample 
        period with the optimal input calculated in the optimization as input.
        To each estimate a normally distributed noise, with the mean 0 
        and standard deviation 0.5% of the nominal value of each state, is 
        added. The MPC object uses the result from the previous optimization as
        initial guess for the next optimization (for all but the first 
        optimization, where the simulation result from #1 is used instead).

   (3.) If with_plots is True we compile the same optimization problem again 
        and define the options so that the op has the same options and 
        resolution as the op we solved through the MPC-class. By same 
        resolution we mean that both op should have the same mesh and blocking 
        factors. This allows us to compare the MPC-results to an open loop 
        optimization. Note that the MPC-results contains noise while the open 
        loop optimization does not. 

    """
    ### 1. Compute initial guess trajectories by means of simulation
    # Locate the Modelica and Optimica code
    file_path = os.path.join(get_files_path(), "CSTR.mop")

    # Compile and load the model used for simulation
    sim_fmu = compile_fmu("CSTR.CSTR_MPC_Model", file_path, 
                            compiler_options={"state_initial_equations":True})
    sim_model = load_fmu(sim_fmu)

    # Define stationary point A and set initial values and inputs
    c_0_A = 956.271352
    T_0_A = 250.051971
    sim_model.set('_start_c', c_0_A)
    sim_model.set('_start_T', T_0_A)
    sim_model.set('Tc', 280)
    
    opts = sim_model.simulate_options()
    opts["CVode_options"]["maxh"] = 0.0
    opts["ncp"] = 0
    
    init_res = sim_model.simulate(start_time=0., final_time=150, options=opts)

    ### 2. Define the optimal control problem and solve it using the MPC class
    # Compile and load optimization problem
    op = transfer_optimization_problem("CSTR.CSTR_MPC", file_path,
                            compiler_options={"state_initial_equations":True})

    # Define MPC options
    sample_period = 3                           # s
    horizon = 33                                # Samples on the horizon
    n_e_per_sample = 1                          # Collocation elements / sample
    n_e = n_e_per_sample*horizon                # Total collocation elements
    finalTime = 150                             # s
    number_samp_tot = int(finalTime/sample_period)   # Total number of samples to do

    # Create blocking factors with quadratic penalty and bound on 'Tc'
    bf_list = [n_e_per_sample]*(horizon/n_e_per_sample)
    factors = {'Tc': bf_list}
    du_quad_pen = {'Tc': 500}
    du_bounds = {'Tc': 30}
    bf = BlockingFactors(factors, du_bounds, du_quad_pen)

    # Set collocation options
    opt_opts = op.optimize_options()
    opt_opts['n_e'] = n_e
    opt_opts['n_cp'] = 2
    opt_opts['init_traj'] = init_res
    opt_opts['blocking_factors'] = bf

    if with_plots:
        # Compile and load a new instance of the op to compare the MPC results 
        # with an open loop optimization 
        op_open_loop = transfer_optimization_problem(
            "CSTR.CSTR_MPC", file_path,
            compiler_options={"state_initial_equations":True})
        op_open_loop.set('_start_c', float(c_0_A))
        op_open_loop.set('_start_T', float(T_0_A)) 
        
        # Copy options from MPC optimization
        open_loop_opts = copy.deepcopy(opt_opts)
        
        # Change n_e and blocking_factors so op_open_loop gets the same 
        # resolution as op
        open_loop_opts['n_e'] = number_samp_tot
        
        bf_list_ol = [n_e_per_sample]*(number_samp_tot/n_e_per_sample)
        factors_ol = {'Tc': bf_list_ol}
        bf_ol = BlockingFactors(factors_ol, du_bounds, du_quad_pen)
        open_loop_opts['blocking_factors'] = bf_ol
        open_loop_opts['IPOPT_options']['print_level'] = 0

    constr_viol_costs = {'T': 1e6}

    # Create the MPC object
    MPC_object = MPC(op, opt_opts, sample_period, horizon, 
                    constr_viol_costs=constr_viol_costs, noise_seed=1)

    # Set initial state
    x_k = {'_start_c': c_0_A, '_start_T': T_0_A }

    # Update the state and optimize number_samp_tot times
    for k in range(number_samp_tot):

        # Update the state and compute the optimal input for next sample period
        MPC_object.update_state(x_k)
        u_k = MPC_object.sample()

        # Reset the model and set the new initial states before simulating
        # the next sample period with the optimal input u_k
        sim_model.reset()
        sim_model.set(list(x_k.keys()), list(x_k.values()))
        sim_res = sim_model.simulate(start_time=k*sample_period, 
                                     final_time=(k+1)*sample_period, 
                                     input=u_k, options=opts)

        # Extract state at end of sample_period from sim_res and add Gaussian
        # noise with mean 0 and standard deviation 0.005*(state_current_value)
        x_k = MPC_object.extract_states(sim_res, mean=0, st_dev=0.005)


    # Extract variable profiles
    MPC_object.print_solver_stats()
    complete_result = MPC_object.get_complete_results()
    c_res_comp = complete_result['c']
    T_res_comp = complete_result['T']
    Tc_res_comp = complete_result['Tc']
    time_res_comp = complete_result['time']

    # Verify solution for testing purposes
    try:
        import casadi
    except:
        pass
    else:
        Tc_norm = N.linalg.norm(Tc_res_comp) / N.sqrt(len(Tc_res_comp))
        assert(N.abs(Tc_norm - 311.7362) < 1e-3)
        c_norm = N.linalg.norm(c_res_comp) / N.sqrt(len(c_res_comp))
        assert(N.abs(c_norm - 653.5369) < 1e-3)
        T_norm = N.linalg.norm(T_res_comp) / N.sqrt(len(T_res_comp))
        assert(N.abs(T_norm - 328.0852) < 1e-3)
    
    # Plot the results
    if with_plots: 
        ### 3. Solve the original optimal control problem without MPC
        res = op_open_loop.optimize(options=open_loop_opts)
        c_res = res['c']
        T_res = res['T']
        Tc_res = res['Tc']
        time_res = res['time']
        
        # Get reference values
        Tc_ref = op.get('Tc_ref')
        T_ref = op.get('T_ref')
        c_ref = op.get('c_ref')

        # Plot
        plt.close('MPC')
        plt.figure('MPC')
        plt.subplot(3, 1, 1)
        plt.plot(time_res_comp, c_res_comp)
        plt.plot(time_res, c_res )
        plt.plot([time_res[0],time_res[-1]],[c_ref,c_ref],'--')
        plt.legend(('MPC with noise', 'Open-loop without noise', 'Reference value'))
        plt.grid()
        plt.ylabel('Concentration')
        plt.title('Simulated trajectories')

        plt.subplot(3, 1, 2)
        plt.plot(time_res_comp, T_res_comp)
        plt.plot(time_res, T_res)
        plt.plot([time_res[0],time_res[-1]],[T_ref,T_ref], '--')
        plt.grid()
        plt.ylabel('Temperature [C]')

        plt.subplot(3, 1, 3)
        plt.step(time_res_comp, Tc_res_comp)
        plt.step(time_res, Tc_res)
        plt.plot([time_res[0],time_res[-1]],[Tc_ref,Tc_ref], '--')
        plt.grid()
        plt.ylabel('Cooling temperature [C]')
        plt.xlabel('time')
        plt.show()
Example #7
0
            class_name = "Circuit"
            file_paths = "circuit.mo"
            opts = {
                'eliminate_alias_variables': True,
                'generate_html_diagnostics': True,
                'variability_propagation': False
            }
            model = transfer_model(class_name,
                                   file_paths,
                                   compiler_options=opts)
            ncp = 500 * model.get('omega')
            init_fmu = load_fmu(
                compile_fmu(class_name, file_paths, compiler_options=opts))
    elif problem == "vehicle":
        sim_res = ResultDymolaTextual(
            os.path.join(get_files_path(), "vehicle_turn_dymola.txt"))
        start_time = 0.
        final_time = sim_res.get_variable_data('time').t[-1]
        ncp = 500
        if source != "Modelica":
            raise ValueError
        class_name = "Car"
        file_paths = os.path.join(get_files_path(), "vehicle_turn.mop")
        opts = {'generate_html_diagnostics': True}
        model = transfer_model(class_name, file_paths, compiler_options=opts)
        init_fmu = load_fmu(
            compile_fmu(class_name, file_paths, compiler_options=opts))

        # Create input data
        # This would have worked if one input was not constant...
        #~ columns = [0]
Example #8
0
def run_demo(with_plots=True):
    """
    This example is based on the multibody mechanics fourbar1 example from the Modelica Standard Library (MSL).

    The MSL example has been modified by adding a torque on the first revolute joint of the pendulum as a top-level
    input. The considered optimization problem is to control the translation along the prismatic joint at the other end
    of the closed kinematic loop.

    This example needs the linear solver MA57 to work.
    """
    # Compile simulation model
    file_paths = (os.path.join(get_files_path(), "Fourbar1.mo"),
                  os.path.join(get_files_path(), "Fourbar1.mop"))
    comp_opts = {
        'inline_functions': 'all',
        'dynamic_states': False,
        'expose_temp_vars_in_fmu': True
    }
    model = load_fmu(
        compile_fmu('Fourbar1.Fourbar1Sim',
                    file_paths,
                    compiler_options=comp_opts))

    # Load trajectories that are optimal subject to a smaller torque constraint and use to generate initial guess
    init_path = os.path.join(get_files_path(), "fourbar1_init.txt")
    init_res = LocalDAECollocationAlgResult(
        result_data=ResultDymolaTextual(init_path))
    t = init_res['time']
    u = init_res['u']
    u_traj = ('u', N.transpose(N.vstack((t, u))))
    sim_res = model.simulate(final_time=1.0, input=u_traj)

    # Set up optimization
    op = transfer_optimization_problem('Opt',
                                       file_paths,
                                       compiler_options=comp_opts)
    opts = op.optimize_options()
    opts['IPOPT_options']['linear_solver'] = "ma57"
    opts['IPOPT_options']['ma57_pivtol'] = 1e-3
    opts['IPOPT_options']['ma57_automatic_scaling'] = "yes"
    opts['IPOPT_options']['mu_strategy'] = "adaptive"
    opts['n_e'] = 20
    opts['init_traj'] = sim_res
    opts['nominal_traj'] = sim_res

    # Solve optimization problem
    res = op.optimize(options=opts)

    # Extract solution
    time = res['time']
    s = res['fourbar1.j2.s']
    phi = res['fourbar1.j1.phi']
    u = res['u']

    # Verify solution for testing purposes
    try:
        import casadi
    except:
        pass
    else:
        cost = float(res.solver.solver_object.output(casadi.NLP_SOLVER_F))
        N.testing.assert_allclose(cost, 1.0455646e-03, rtol=5e-3)

    # Plot solution
    if with_plots:
        plt.close(1)
        plt.figure(1)
        plt.subplot(3, 1, 1)
        plt.plot(time, s)
        plt.ylabel('$s$')
        plt.xlabel('$t$')
        plt.grid()

        plt.subplot(3, 1, 2)
        plt.plot(time, s)
        plt.ylabel('$\phi$')
        plt.xlabel('$t$')
        plt.grid()

        plt.subplot(3, 1, 3)
        plt.plot(time, u)
        plt.ylabel('$u$')
        plt.xlabel('$t$')
        plt.grid()

        plt.show()
def run_demo(with_plots=True):
    """
    This example is based on a combined cycle power plant (CCPP). The model has
    9 states, 128 algebraic variables and 1 control variable. The task is to
    minimize the time required to perform a warm start-up of the power plant.
    This problem has become highly industrially relevant during the last few
    years, due to an increasing need to improve power generation flexibility.
    
    The example consists of the following steps:
    
    1.  Simulating the system using a simple input trajectory.
    
    2.  Solving the optimal control problem using the result from the first
        step to initialize the non-linear program.
       
    3.  Verifying the result from the second step by simulating the system
        once more usng the optimized input trajectory.
    
    The model was developed by Francesco Casella and is published in
    @InProceedings{CFA2011,
      author = "Casella, Francesco and Donida, Filippo and {\AA}kesson, Johan",
      title = "Object-Oriented Modeling and Optimal Control: A Case Study in
               Power Plant Start-Up",
      booktitle = "18th IFAC World Congress",
      address = "Milano, Italy",
      year = 2011,
      month = aug
    }
    """
    ### 1. Compute initial guess trajectories by means of simulation
    # Locate the Modelica and Optimica code
    file_paths = (os.path.join(get_files_path(), "CombinedCycle.mo"),
                  os.path.join(get_files_path(), "CombinedCycleStartup.mop"))

    # Compile the optimization initialization model
    init_sim_fmu = compile_fmu("CombinedCycleStartup.Startup6Reference",
                               file_paths,
                               separate_process=True)

    # Load the model
    init_sim_model = load_fmu(init_sim_fmu)

    # Simulate
    init_res = init_sim_model.simulate(start_time=0., final_time=10000.)

    # Extract variable profiles
    init_sim_plant_p = init_res['plant.p']
    init_sim_plant_sigma = init_res['plant.sigma']
    init_sim_plant_load = init_res['plant.load']
    init_sim_time = init_res['time']

    # Plot the initial guess trajectories
    if with_plots:
        plt.close(1)
        plt.figure(1)
        plt.subplot(3, 1, 1)
        plt.plot(init_sim_time, init_sim_plant_p * 1e-6)
        plt.ylabel('evaporator pressure [MPa]')
        plt.grid(True)
        plt.title('Initial guess obtained by simulation')

        plt.subplot(3, 1, 2)
        plt.plot(init_sim_time, init_sim_plant_sigma * 1e-6)
        plt.grid(True)
        plt.ylabel('turbine thermal stress [MPa]')

        plt.subplot(3, 1, 3)
        plt.plot(init_sim_time, init_sim_plant_load)
        plt.grid(True)
        plt.ylabel('input load [1]')
        plt.xlabel('time [s]')

    ### 2. Solve the optimal control problem
    # Compile model
    from pyjmi import transfer_to_casadi_interface
    op = transfer_to_casadi_interface("CombinedCycleStartup.Startup6",
                                      file_paths)

    # Set options
    opt_opts = op.optimize_options()
    opt_opts['n_e'] = 50  # Number of elements
    opt_opts['init_traj'] = init_res  # Simulation result
    opt_opts['nominal_traj'] = init_res
    opt_opts['verbosity'] = 1

    # Solve the optimal control problem
    opt_res = op.optimize(options=opt_opts)

    # Extract variable profiles
    opt_plant_p = opt_res['plant.p']
    opt_plant_sigma = opt_res['plant.sigma']
    opt_plant_load = opt_res['plant.load']
    opt_time = opt_res['time']
    opt_input = N.vstack([opt_time, opt_plant_load]).T

    # Plot the optimized trajectories
    if with_plots:
        plt.close(2)
        plt.figure(2)
        plt.subplot(3, 1, 1)
        plt.plot(opt_time, opt_plant_p * 1e-6)
        plt.ylabel('evaporator pressure [MPa]')
        plt.grid(True)
        plt.title('Optimized trajectories')

        plt.subplot(3, 1, 2)
        plt.plot(opt_time, opt_plant_sigma * 1e-6)
        plt.grid(True)
        plt.ylabel('turbine thermal stress [MPa]')

        plt.subplot(3, 1, 3)
        plt.plot(opt_time, opt_plant_load)
        plt.grid(True)
        plt.ylabel('input load [1]')
        plt.xlabel('time [s]')

    # Verify solution for testing purposes
    try:
        import casadi
    except:
        pass
    else:
        cost = float(opt_res.solver.solver_object.output(casadi.NLP_SOLVER_F))
        N.testing.assert_allclose(cost, 17492.465548193624, rtol=1e-5)

    ### 3. Simulate to verify the optimal solution
    # Compile model
    sim_fmu = compile_fmu("CombinedCycle.Optimization.Plants.CC0D_WarmStartUp",
                          file_paths)

    # Load model
    sim_model = load_fmu(sim_fmu)

    # Simulate using optimized input
    sim_res = sim_model.simulate(start_time=0.,
                                 final_time=4000.,
                                 input=('load', opt_input))

    # Extract variable profiles
    sim_plant_p = sim_res['p']
    sim_plant_sigma = sim_res['sigma']
    sim_plant_load = sim_res['load']
    sim_time = sim_res['time']

    # Plot the simulated trajectories
    if with_plots:
        plt.close(3)
        plt.figure(3)
        plt.subplot(3, 1, 1)
        plt.plot(opt_time, opt_plant_p * 1e-6, '--', lw=5)
        plt.hold(True)
        plt.plot(sim_time, sim_plant_p * 1e-6, lw=2)
        plt.ylabel('evaporator pressure [MPa]')
        plt.grid(True)
        plt.legend(('optimized', 'simulated'), loc='lower right')
        plt.title('Verification')

        plt.subplot(3, 1, 2)
        plt.plot(opt_time, opt_plant_sigma * 1e-6, '--', lw=5)
        plt.hold(True)
        plt.plot(sim_time, sim_plant_sigma * 1e-6, lw=2)
        plt.ylabel('turbine thermal stress [MPa]')
        plt.grid(True)

        plt.subplot(3, 1, 3)
        plt.plot(opt_time, opt_plant_load, '--', lw=5)
        plt.hold(True)
        plt.plot(sim_time, sim_plant_load, lw=2)
        plt.ylabel('input load [1]')
        plt.xlabel('time [s]')
        plt.grid(True)
        plt.show()

    # Verify solution for testing purposes
    N.testing.assert_allclose(opt_res.final('plant.p'),
                              sim_res.final('p'),
                              rtol=5e-3)
Example #10
0
def run_demo(with_plots=True):
    """
    This example is based on the Hicks-Ray Continuously Stirred Tank 
    Reactors (CSTR) system. The system has two states, the 
    concentration and the temperature. The control input to the system 
    is the temperature of the cooling flow in the reactor jacket. The 
    chemical reaction in the reactor is exothermic, and also 
    temperature dependent; high temperature results in high reaction 
    rate.
    
    This example serves to illustrate some of the key features of the 
    CasADi-based Moving Horizon Estimator (MHE). 
    
    MHE solves a finite horizon optimization problem at every time 
    step to generate an estimate of the next value of the states.
    The cost function used by the MHE is on the form
    
    cost = sum_{k = T-N}^{N-1}(w_kQ_k^{-1}w_k^T + v_kR_k^{-1}v_k^T) + 
    Z(x_{T-N})
    
    where w is the process noise, v the measurement noise and Z(...) 
    the so called arrival cost term. The arrival cost term summarizes 
    the information outside of the finite horizon of data in the sum. 
    The arrival cost is approximated so that the size of the 
    optimization does not grow with the time. Currently the 
    approximation used is the EKF covariance update. Meaning that the 
    arrival cost approximation is on the form 
    
    Z^hat(x_{T-N}) = (x^bar_{T-N} - x^hat_{T-N})P_{T-N}^{-1}
    (x^bar_{T-N} - x^hat_{T-N})^T
    
    The example will demonstrate how one can use the MHE class to 
    perform state estimation using a FMUModel object to generate 
    measurement data.
    """
    #Get the name and location of the Modelica package
    file_path = os.path.join(get_files_path(), "CSTR.mop")

    #Transfer the OptimizationProblem object, using the
    #"state_initial_equations" option to create new initial equations and new
    #parameters for those equations. This is required by the MHE class
    op = transfer_optimization_problem(
        'CSTR.CSTR',
        file_path,
        accept_model=True,
        compiler_options={"state_initial_equations": True})

    #Compile the FMU with the same option as for the OptimizationProblem
    fmu = compile_fmu('CSTR.CSTR',
                      file_path,
                      compiler_options={"state_initial_equations": True})
    #Load the FMU
    model = load_fmu(fmu)

    #Define the time interval and the number of points
    sim_time = 3.
    nbr_of_points = 31
    #Calculate the corresponding sample time
    sample_time = sim_time / (nbr_of_points - 1)

    #Create an array of the time points
    time = N.linspace(0., sim_time, nbr_of_points)

    ###Create noise for the measurement data
    #Create the continuous covariance matrices
    Q = N.array([[2.]])
    R = N.array([[10., 0.], [0., 2.]])
    #The expectations
    w_my = N.array([0.])
    v_my = N.array([0., 0.])
    ##Get the noise sequences
    #Process noise
    #Use same seed for consistent results
    N.random.seed(2)
    w = N.transpose(N.random.multivariate_normal(w_my, Q, nbr_of_points))
    #Measurement noise
    N.random.seed(3)
    v = N.transpose(N.random.multivariate_normal(v_my, R, nbr_of_points))

    ###Chose a control signal
    u = 280. + 25. * signal.square(2. * N.pi * time)

    ###Define the inputs for the MHE object
    ##See the documentation of the MHEOptions for more details
    #Create the options object
    MHE_opts = MHEOptions()
    #Process noise covariance
    MHE_opts['process_noise_cov'] = [('Tc', 20.)]
    #The names of the input signals acting as control signals
    MHE_opts['input_names'] = ['Tc']
    #Chose what variables are measured and their covariance structure
    #The two definitions below are equivalent
    MHE_opts['measurement_cov'] = [('c', 10.), ('T', 1.)]
    MHE_opts['measurement_cov'] = [(['c', 'T'], N.array([[1., 0.0], [0.0,
                                                                     0.2]]))]
    #Error covariance matrix
    MHE_opts['P0_cov'] = [('c', 10.), ('T', 5.)]

    ##The initial guess of the states
    x_0_guess = dict([('c', 990.), ('T', 355.)])
    #Initial value of the simulation
    x_0 = dict([('c', 1000.), ('T', 350.)])

    ##Use mhe_initial_values module or some equivalent method to get the
    #initial values of the state derivatives and the algebraic variables
    #Control signal for time step zero
    u_0 = {'Tc': u[0]}

    (dx_0, c_0) = initv.optimize_for_initial_values(op, x_0_guess, u_0,
                                                    MHE_opts)

    #Decide the horizon length
    horizon = 8

    ##Create the MHE object
    MHE_object = MHE(op, sample_time, horizon, x_0_guess, dx_0, c_0, MHE_opts)

    #Create a structure for saving the estimates
    x_est = {'c': [x_0_guess['c']], 'T': [x_0_guess['T']]}
    #Create a structure for saving the simulated data
    x = {'c': [x_0['c']], 'T': [x_0['T']]}
    #Create the structure for the measured data
    y = {'c': [], 'T': []}
    #Loop over estimation and simulation
    for t in range(1, nbr_of_points):
        #Create the measurement data from the simulated data and added noise
        y['c'].append(x['c'][-1] + v[0, t - 1])
        y['T'].append(x['T'][-1] + v[1, t - 1])
        #Create list of tuples with (name, measurement) structure
        y_t = [('c', y['c'][-1]), ('T', y['T'][-1])]
        #Create list of tuples with (name, input) structure
        u_t = [('Tc', u[t - 1])]
        #Estimate
        x_est_t = MHE_object.step(u_t, y_t)

        #Add the results to x_est
        for key in list(x_est.keys()):
            x_est[key].append(x_est_t[key])

        ###Prepare the simulation
        #Create the input object
        u_traj = N.transpose(N.vstack((0., u[t])))
        input_object = ('Tc', u_traj)

        #Set the initial values of the states
        for (key, list) in list(x.items()):
            model.set('_start_' + key, list[-1])

        #Simulate with one communication point to get the value at the right point
        res = model.simulate(final_time=sample_time,
                             input=input_object,
                             options={'ncp': 1})

        #Extract the state values from the result object
        for key in list(x.keys()):
            x[key].append(res[key][-1])
        #reset the FMU
        model.reset()

    #Add the last measurement
    y['c'].append(x['c'][-1] + v[0, -1])
    y['T'].append(x['T'][-1] + v[1, -1])

    if with_plots:
        plt.close('MHE')
        plt.figure('MHE')
        plt.subplot(3, 1, 1)
        plt.plot(time, x_est['c'])
        plt.plot(time, x['c'], ls='--', color='k')
        plt.plot(time, y['c'], ls='-', marker='+', mfc='k', mec='k', mew=1.)
        plt.legend(('Concentration estimate', 'Simulated concentration',
                    'Measured concentration'))
        plt.grid()
        plt.ylabel('Concentration')

        plt.subplot(3, 1, 2)
        plt.plot(time, x_est['T'])
        plt.plot(time, x['T'], ls='--', color='k')
        plt.plot(time, y['T'], ls='-', marker='+', mfc='k', mec='k', mew=1.)
        plt.legend(('Temperature estimate', 'Simulated temperature',
                    'Measured temperature'))
        plt.grid()
        plt.ylabel('Temperature')

        plt.subplot(3, 1, 3)
        plt.step(time, u)
        plt.grid()
        plt.ylabel('Cooling temperature')
        plt.xlabel('time')
        plt.show()
Example #11
0
def run_demo(with_plots=True):
    """
    This example demonstrates the solution of optimal experimental design (OED) problems.

    The example is based on a fed-batch reactor with two states, one algebraic variable. The model has 4 parameters to
    be estimated based on discrete measurements of the two states. The design space consists of two piecewise constant
    inputs, which are to be designed in order to maximize the information content in the measurements according to the
    A-criterion. In order to evaluate the objective, the model is augmented with variables and equations for the
    sensitivities of all the nidek variables with respect to the unknown parameters using forward sensitivities, which
    allows the formulation of the Fisher information matrix. An initial guess of the solution is generated by simulating
    the system with constant input values.
    """
    # Define outputs, parameters, and time points for needed sensitivities, and the experiment variance matrix sigma
    outputs = ['y1', 'y2']
    parameters = ['theta1', 'theta2', 'theta3', 'theta4']
    time_points = [2., 4., 6., 8., 10., 12., 14., 16., 18., 20.]
    sigma = N.array([[10., 0.], [0., 10.]])

    # Define nominal input values used as initial guess
    u_1_nom = 0.1
    u_2_nom = 15

    # Simulate model with sensititivies to generate initial guess for optimization
    file_path = os.path.join(get_files_path(), "fed_batch_reactor.mop")
    model = load_fmu(
        compile_fmu('FedBatchReactor',
                    file_path,
                    compiler_options={"generate_ode_jacobian": True},
                    version=2.0))
    sim_opts = model.simulate_options()
    sim_opts['sensitivities'] = parameters
    sim_opts['CVode_options']['rtol'] = 1e-8
    sim_res = model.simulate(options=sim_opts,
                             input=(('u1', 'u2'), lambda t:
                                    (u_1_nom, u_2_nom)),
                             final_time=20.)

    # Compile optimization problem
    op = transfer_optimization_problem('FedBatchReactor_OED', file_path)

    # Transform the optimization problem into an OED problem
    op.setup_oed(outputs, parameters, sigma, time_points, "T")

    # Set solver options
    opts = op.optimize_options()
    opts['init_traj'] = sim_res  # Initial guess
    opts['nominal_traj'] = sim_res
    opts['blocking_factors'] = 10 * [3]  # Piecewise constant inputs
    opts['n_e'] = 30  # Number of collocation elements
    opts['IPOPT_options']['linear_solver'] = "ma27"
    opts['verbosity'] = 1

    # Solve
    opt_res = op.optimize(options=opts)

    # Simulate optimal inputs to verify optimization discretization
    model.reset()
    sim_opts = model.simulate_options()
    sim_opts['sensitivities'] = parameters
    sim_opts['CVode_options']['rtol'] = 1e-8
    res = model.simulate(options=sim_opts,
                         input=opt_res.get_opt_input(),
                         final_time=20.)

    # Extract solution
    time = res['time']
    u1 = res['u1']
    u2 = res['u2']
    y1 = res['y1']
    y2 = res['y2']
    opt_time = opt_res['time']
    opt_u1 = opt_res['u1']
    opt_u2 = opt_res['u2']
    opt_y1 = opt_res['y1']
    opt_y2 = opt_res['y2']

    # Verify solution for testing purposes
    try:
        import casadi
    except:
        pass
    else:
        cost = float(opt_res.solver.solver_object.output(casadi.NLP_SOLVER_F))
        N.testing.assert_allclose(cost, -1.311920e+07, rtol=1e-3)

    # Plot solution
    if with_plots:
        plt.close(1)
        plt.figure(1)
        lw = 1.5
        ls = '-'
        plt.plot(time, y1, ls=ls, c='b', lw=lw)
        plt.plot(time, y2, ls=ls, c='g', lw=lw)
        plt.plot(time, u1, ls=ls, c='r', lw=lw)
        plt.plot(time, u2, ls=ls, c='c', lw=lw)
        ls = '--'
        plt.plot(opt_time, opt_y1, ls=ls, c='b', lw=lw)
        plt.plot(opt_time, opt_y2, ls=ls, c='g', lw=lw)
        plt.legend(
            ['y1 sim', 'y2 sim', 'u1 sim', 'u2 sim', 'y1 opt', 'y2 opt'])
        plt.show()
Example #12
0
def run_demo(with_plots=True):
    """
    Demonstrate symbolic elimination.
    """
    # Compile and load optimization problem
    file_path = os.path.join(get_files_path(), "JMExamples_opt.mop")
    compiler_options = {'equation_sorting': True, 'automatic_tearing': True}
    op = transfer_optimization_problem("JMExamples_opt.EliminationExample",
                                       file_path, compiler_options)

    # Set up and perform elimination
    elim_opts = EliminationOptions()
    elim_opts['ineliminable'] = [
        'y1'
    ]  # Provide list of variable names to not eliminate
    # Variables with any of the following properties are recommended to mark as ineliminable:
    # Potentially active bounds
    # Occurring in the objective or constraints
    # Numerically unstable pivots (difficult to predict)
    if with_plots:
        elim_opts['draw_blt'] = True
        elim_opts['draw_blt_strings'] = True
    op = BLTOptimizationProblem(op, elim_opts)

    # Optimize and extract solution
    res = op.optimize()
    x1 = res['x1']
    x2 = res['x2']
    y1 = res['y1']
    u = res['u']
    time = res['time']

    # Plot
    if with_plots:
        plt.figure(1)
        plt.clf()
        plt.subplot(4, 1, 1)
        plt.plot(time, x1)
        plt.grid()
        plt.ylabel('x1')

        plt.subplot(4, 1, 2)
        plt.plot(time, x2)
        plt.grid()
        plt.ylabel('x2')

        plt.subplot(4, 1, 3)
        plt.plot(time, y1)
        plt.grid()
        plt.ylabel('y1')

        plt.subplot(4, 1, 4)
        plt.plot(time, u)
        plt.grid()
        plt.ylabel('u')
        plt.xlabel('time')
        plt.show()

    # Verify solution for testing purposes
    try:
        import casadi
    except:
        pass
    else:
        cost = float(res.solver.solver_object.getOutput('f'))
        N.testing.assert_allclose(cost, 1.0818134, rtol=1e-4)
Example #13
0
                (8, 7),
                (8, 8),
            ]
        else:
            class_name = "Circuit"
            file_paths = "circuit.mo"
            opts = {
                "eliminate_alias_variables": True,
                "generate_html_diagnostics": True,
                "variability_propagation": False,
            }
            model = transfer_model(class_name, file_paths, compiler_options=opts)
            ncp = 500 * model.get("omega")
            init_fmu = load_fmu(compile_fmu(class_name, file_paths, compiler_options=opts))
    elif problem == "vehicle":
        sim_res = ResultDymolaTextual(os.path.join(get_files_path(), "vehicle_turn_dymola.txt"))
        start_time = 0.0
        final_time = sim_res.get_variable_data("time").t[-1]
        ncp = 500
        if source != "Modelica":
            raise ValueError
        class_name = "Car"
        file_paths = os.path.join(get_files_path(), "vehicle_turn.mop")
        opts = {"generate_html_diagnostics": True}
        model = transfer_model(class_name, file_paths, compiler_options=opts)
        init_fmu = load_fmu(compile_fmu(class_name, file_paths, compiler_options=opts))

        # Create input data
        # This would have worked if one input was not constant...
        # ~ columns = [0]
        # ~ columns += [sim_res.get_column(input_var.getName()) for input_var in model.getVariables(model.REAL_INPUT)]
Example #14
0
def run_demo(with_plots=True):
    """
    This example is based on a single-track model of a car with tire dynamics.
    The optimization problem is to minimize the duration of a 90-degree turn
    with actuators on the steer angle and front and rear wheel torques.

    This example also demonstrates the usage of blocking factors, to enforce
    piecewise constant inputs.

    This example needs the linear solver MA27 to work.
    """
    # Set up optimization
    mop_path = os.path.join(get_files_path(), "vehicle_turn.mop")
    op = transfer_optimization_problem('Turn', mop_path)
    opts = op.optimize_options()
    opts['IPOPT_options']['linear_solver'] = "ma27"
    opts['IPOPT_options']['tol'] = 1e-10
    opts['n_e'] = 60

    # Set blocking factors
    factors = {'delta_u': opts['n_e'] / 2 * [2],
               'Twf_u': opts['n_e'] / 4 * [4],
               'Twr_u': opts['n_e'] / 4 * [4]}
    rad2deg = 180. / (2*N.pi)
    du_bounds = {'delta_u': 2. / rad2deg}
    bf = BlockingFactors(factors, du_bounds=du_bounds)
    opts['blocking_factors'] = bf

    # Use Dymola simulation result as initial guess
    init_path = os.path.join(get_files_path(), "vehicle_turn_dymola.txt")
    init_guess = ResultDymolaTextual(init_path)
    opts['init_traj'] = init_guess

    # Solve optimization problem
    res = op.optimize(options=opts)

    # Extract solution
    time = res['time']
    X = res['car.X']
    Y = res['car.Y']
    delta = res['delta_u']
    Twf = res['Twf_u']
    Twr = res['Twr_u']
    Ri = op.get('Ri')
    Ro = op.get('Ro')

    # Verify result
    N.testing.assert_allclose(time[-1], 4.0118, rtol=5e-3)

    # Plot solution
    if with_plots:
        # Plot road
        plt.close(1)
        plt.figure(1)
        plt.plot(X, Y, 'b')
        xi = N.linspace(0., Ri, 100)
        xo = N.linspace(0., Ro, 100)
        yi = (Ri**8 - xi**8) ** (1./8.)
        yo = (Ro**8 - xo**8) ** (1./8.)
        plt.plot(xi, yi, 'r--')
        plt.plot(xo, yo, 'r--')
        plt.xlabel('X [m]')
        plt.ylabel('Y [m]')
        plt.legend(['position', 'road'], loc=3)

        # Plot inputs
        plt.close(2)
        plt.figure(2)
        plt.plot(time, delta * rad2deg, drawstyle='steps-post')
        plt.plot(time, Twf * 1e-3, drawstyle='steps-post')
        plt.plot(time, Twr * 1e-3, drawstyle='steps-post')
        plt.xlabel('time [s]')
        plt.legend(['delta [deg]', 'Twf [kN]', 'Twr [kN]'], loc=4)
        plt.show()
Example #15
0
            varis_str = ['$u_0$', '$u_1$', '$u_2$', '$u_L$', '$\dot i_L$', '$i_0$',
                         '$i_1$', '$i_2$', '$i_3$']
            edg_indices = [(0, 0), (1, 1), (1, 6), (2, 2), (2, 7), (3, 2), (3, 8),
                           (4, 3), (4, 4), (5, 0), (5, 1), (5, 2), (6, 1), (6, 2),
                           (6, 3), (7, 5), (7, 6), (8, 6), (8, 7), (8, 8)]
        else:
            caus_opts['tear_vars'] = ['i3']
            caus_opts['tear_res'] = [7]
            class_name = "Circuit"
            file_paths = "circuit.mo"
            opts = {'eliminate_alias_variables': False}
            op = transfer_optimization_problem(class_name, file_paths, compiler_options=opts, accept_model=True)
            opt_opts = op.optimize_options()
    elif problem == "vehicle":
        caus_opts['uneliminable'] = ['car.Fxf', 'car.Fxr', 'car.Fyf', 'car.Fyr']
        sim_res = ResultDymolaTextual(os.path.join(get_files_path(), "vehicle_turn_dymola.txt"))
        #~ sim_res = ResultDymolaTextual("vehicle_sol.txt")
        ncp = 500
        if source != "Modelica":
            raise ValueError
        class_name = "Turn"
        file_paths = os.path.join(get_files_path(), "vehicle_turn.mop")
        compiler_opts = {'generate_html_diagnostics': True}
        op = transfer_optimization_problem(class_name, file_paths, compiler_options=compiler_opts)

        opt_opts = op.optimize_options()
        opt_opts['IPOPT_options']['linear_solver'] = "ma57"
        opt_opts['IPOPT_options']['tol'] = 1e-9
        #~ opt_opts['IPOPT_options']['derivative_test'] = "only-second-order"
        #~ opt_opts['IPOPT_options']['hessian_approximation'] = "limited-memory"
        #~ opt_opts['order'] = "reverse"
Example #16
0
def run_demo(with_plots=True):
    """
    This example demonstrates how to solve parameter estimation problmes.

    The system is tanks with connected inlets and outlets. The objective is to
    estimate the outlet area of two of the tanks based on measurement data.
    """
    # Compile and load FMU, which is used for simulation
    file_path = os.path.join(get_files_path(), "QuadTankPack.mop")
    model = load_fmu(compile_fmu('QuadTankPack.QuadTank', file_path))

    # Transfer problem to CasADi Interface, which is used for estimation
    op = transfer_optimization_problem("QuadTankPack.QuadTank_ParEstCasADi",
                                       file_path)

    # Set initial states in model, which are stored in the optimization problem
    x_0_names = ['x1_0', 'x2_0', 'x3_0', 'x4_0']
    x_0_values = op.get(x_0_names)
    model.set(x_0_names, x_0_values)
    
    # Load measurement data from file
    data_path = os.path.join(get_files_path(), "qt_par_est_data.mat")
    data = loadmat(data_path, appendmat=False)

    # Extract data series
    t_meas = data['t'][6000::100, 0] - 60
    y1_meas = data['y1_f'][6000::100, 0] / 100
    y2_meas = data['y2_f'][6000::100, 0] / 100
    y3_meas = data['y3_d'][6000::100, 0] / 100
    y4_meas = data['y4_d'][6000::100, 0] / 100
    u1 = data['u1_d'][6000::100, 0]
    u2 = data['u2_d'][6000::100, 0]
    
    # Plot measurements and inputs
    if with_plots:
        plt.close(1)
        plt.figure(1)
        plt.subplot(2, 2, 1)
        plt.plot(t_meas, y3_meas)
        plt.title('x3')
        plt.grid()
        plt.subplot(2, 2, 2)
        plt.plot(t_meas, y4_meas)
        plt.title('x4')
        plt.grid()
        plt.subplot(2, 2, 3)
        plt.plot(t_meas, y1_meas)
        plt.title('x1')
        plt.xlabel('t[s]')
        plt.grid()
        plt.subplot(2, 2, 4)
        plt.plot(t_meas, y2_meas)
        plt.title('x2')
        plt.xlabel('t[s]')
        plt.grid()

        plt.close(2)
        plt.figure(2)
        plt.subplot(2, 1, 1)
        plt.plot(t_meas, u1)
        plt.hold(True)
        plt.title('u1')
        plt.grid()
        plt.subplot(2, 1, 2)
        plt.plot(t_meas, u2)
        plt.title('u2')
        plt.xlabel('t[s]')
        plt.hold(True)
        plt.grid()

    # Build input trajectory matrix for use in simulation
    u = N.transpose(N.vstack([t_meas, u1, u2]))
    
    # Simulate model response with nominal parameter values
    res_sim = model.simulate(input=(['u1', 'u2'], u),
                             start_time=0., final_time=60.)

    # Load simulation result
    x1_sim = res_sim['x1']
    x2_sim = res_sim['x2']
    x3_sim = res_sim['x3']
    x4_sim = res_sim['x4']
    t_sim  = res_sim['time']
    u1_sim = res_sim['u1']
    u2_sim = res_sim['u2']

    # Check simulation results for testing purposes
    assert N.abs(res_sim.final('x1') - 0.05642485) < 1e-3
    assert N.abs(res_sim.final('x2') - 0.05510478) < 1e-3
    assert N.abs(res_sim.final('x3') - 0.02736532) < 1e-3
    assert N.abs(res_sim.final('x4') - 0.02789808) < 1e-3
    assert N.abs(res_sim.final('u1') - 6.0) < 1e-3
    assert N.abs(res_sim.final('u2') - 5.0) < 1e-3

    # Plot simulation result
    if with_plots:
        plt.figure(1)
        plt.subplot(2, 2, 1)
        plt.plot(t_sim, x3_sim)
        plt.subplot(2, 2, 2)
        plt.plot(t_sim, x4_sim)
        plt.subplot(2, 2, 3)
        plt.plot(t_sim, x1_sim)
        plt.subplot(2, 2, 4)
        plt.plot(t_sim, x2_sim)

        plt.figure(2)
        plt.subplot(2, 1, 1)
        plt.plot(t_sim, u1_sim, 'r')
        plt.subplot(2, 1, 2)
        plt.plot(t_sim, u2_sim, 'r')

    # Create external data object for optimization
    Q = N.diag([1., 1., 10., 10.])
    data_x1 = N.vstack([t_meas, y1_meas])
    data_x2 = N.vstack([t_meas, y2_meas])
    data_u1 = N.vstack([t_meas, u1])
    data_u2 = N.vstack([t_meas, u2])
    quad_pen = OrderedDict()
    quad_pen['x1'] = data_x1
    quad_pen['x2'] = data_x2
    quad_pen['u1'] = data_u1
    quad_pen['u2'] = data_u2
    external_data = ExternalData(Q=Q, quad_pen=quad_pen)

    # Set optimization options and optimize
    opts = op.optimize_options()
    opts['n_e'] = 60 # Number of collocation elements
    opts['external_data'] = external_data
    opts['init_traj'] = res_sim
    opts['nominal_traj'] = res_sim
    res = op.optimize(options=opts) # Solve estimation problem

    # Extract estimated values of parameters
    a1_opt = res.initial("a1")
    a2_opt = res.initial("a2")

    # Print and assert estimated parameter values
    print(('a1: ' + str(a1_opt*1e4) + 'cm^2'))
    print(('a2: ' + str(a2_opt*1e4) + 'cm^2'))
    a_ref = [0.02656702, 0.02713898]
    N.testing.assert_allclose(1e4 * N.array([a1_opt, a2_opt]),
                              a_ref, rtol=1e-4)

    # Load state profiles
    x1_opt = res["x1"]
    x2_opt = res["x2"]
    x3_opt = res["x3"]
    x4_opt = res["x4"]
    u1_opt = res["u1"]
    u2_opt = res["u2"]
    t_opt  = res["time"]

    # Plot estimated trajectories
    if with_plots:
        plt.figure(1)
        plt.subplot(2, 2, 1)
        plt.plot(t_opt, x3_opt, 'k')
        plt.subplot(2, 2, 2)
        plt.plot(t_opt, x4_opt, 'k')
        plt.subplot(2, 2, 3)
        plt.plot(t_opt, x1_opt, 'k')
        plt.subplot(2, 2, 4)
        plt.plot(t_opt, x2_opt, 'k')

        plt.figure(2)
        plt.subplot(2, 1, 1)
        plt.plot(t_opt, u1_opt, 'k')
        plt.subplot(2, 1, 2)
        plt.plot(t_opt, u2_opt, 'k')
        plt.show()
Example #17
0
def run_demo(with_plots=True):
    """
    This example is about moving a cart with an attached pendulum from one
    position to another, while starting and ending in steady state and avoiding
    an ellipticla obstacle for the pendulum.

    This example is a part of the third lab in the course FRTN05 Nonlinear
    Control and Servo systems at the Department of Automatic Control at Lund
    University, Sweden. In the lab, the trajectories generated by this script
    are realized by tracking them with linear MPC.

    The model has 4 states: Cart position and velocity, pendulum angle and
    angular velocity. A nearly optimal initial guess has been precomputed and
    is used in this script.
    
    The problem was developed by Pontus Giselsson and is published in
    @InProceedings{mod09pg,
      author = "Giselsson, Pontus and {\AA}kesson, Johan and Robertsson, Anders",
      title = "Optimization of a Pendulum System using {Optimica} and {Modelica}",
      booktitle = "7th International Modelica Conference 2009",
      address = "Como, Italy",
      year = 2009,
      month = sep,
    }
    """
    # Create compiler and compile the pendulum model
    file_path = os.path.join(get_files_path(), "cart_pendulum.mop")
    pend_opt = transfer_optimization_problem("CartPendulum", file_path)

    # Define number of elements in the discretization grid and
    # number of collocation points in each element
    n_e = 150
    n_cp = 3

    # Initialize the optimization problem with precomputed initial guess
    result_file_path = os.path.join(get_files_path(),
                                    'cart_pendulum_result.txt')
    init_res = ResultDymolaTextual(result_file_path)

    # Solve the optimization problem
    opts = pend_opt.optimize_options()
    opts['IPOPT_options']['max_iter'] = 1000
    opts['IPOPT_options']['linear_solver'] = "mumps"
    opts['IPOPT_options']['tol'] = 1e-12
    opts['n_e'] = n_e
    opts['n_cp'] = n_cp
    opts['init_traj'] = init_res
    res = pend_opt.optimize(options=opts)

    # Extract variable profiles and plot the results
    a_ref = res['a_ref']
    x_p = res['x_p']
    y_p = res['y_p']
    t = res['time']

    if with_plots:
        plt.close(1)
        plt.figure(1)
        plt.plot(t, a_ref)
        plt.grid()
        plt.title('Input signal to process ($a_{ref}$)')
        plt.xlabel('Time (s)')
        plt.ylabel('Acceleration $m/s^2$')

        plt.close(2)
        plt.figure(2)
        plt.plot(x_p, y_p)
        plt.grid()
        plt.title('Pendulum end-point path and obstacle')
        plt.xlabel('x-coordinate (m)')
        plt.ylabel('y-coordinate (m)')

        x_obst = N.linspace(-0.35, -0.25)
        y_obst = N.sqrt(1 - ((x_obst + 0.3) / 0.05)**2) * 0.3 - 0.4

        x_track = N.linspace(-1.45, 0.1)
        y_track = N.zeros(N.size(x_track))

        plt.plot(x_obst, y_obst)
        plt.plot(x_track, y_track, '--')

        plt.show()
Example #18
0
with_plots = True
#~ with_plots = False
blt = True
#~ blt = False
caus_opts = sp.CausalizationOptions()
#~ caus_opts['plots'] = True
#~ caus_opts['draw_blt'] = True
#~ caus_opts['solve_blocks'] = True
#~ caus_opts['ad_hoc_scale'] = True
#~ caus_opts['inline'] = False
#~ caus_opts['closed_form'] = True
#~ caus_opts['inline_solved'] = True

caus_opts['uneliminable'] = ['car.Fxf', 'car.Fxr', 'car.Fyf', 'car.Fyr']
sim_res = ResultDymolaTextual(
    os.path.join(get_files_path(), "vehicle_turn_dymola.txt"))
ncp = 500
class_name = "Turn"
file_paths = os.path.join(get_files_path(), "vehicle_turn.mop")
compiler_opts = {'generate_html_diagnostics': True}
op = transfer_optimization_problem(class_name,
                                   file_paths,
                                   compiler_options=compiler_opts)

opt_opts = op.optimize_options()
opt_opts['IPOPT_options']['linear_solver'] = "ma27"
opt_opts['IPOPT_options']['tol'] = 1e-9
opt_opts['IPOPT_options']['ma27_pivtol'] = 1e-4
opt_opts['IPOPT_options']['print_kkt_blocks_to_mfile'] = -1
opt_opts['IPOPT_options']['max_iter'] = 200
opt_opts['n_e'] = 37
plt.rcParams.update({'text.usetex': False})

with_plots = True
with_plots = False
expand_to_sx = True
#~ expand_to_sx = False
caus_opts = sp.CausalizationOptions()
#~ caus_opts['plots'] = True
#~ caus_opts['draw_blt'] = True
#~ caus_opts['solve_blocks'] = True
#~ caus_opts['inline'] = False
#~ caus_opts['closed_form'] = True
caus_opts['dense_tol'] = 1e10
caus_opts['inline_solved'] = True

sim_res = ResultDymolaTextual(os.path.join(get_files_path(), "vehicle_turn_dymola.txt"))
#~ sim_res = ResultDymolaTextual("opt_asphalt.txt")
start_time = 0.
final_time = sim_res.get_variable_data('time').t[-1]
ncp = 100
class_name = "Car"
file_paths = os.path.join(get_files_path(), "vehicle_turn.mop")
opts = {'generate_html_diagnostics': True, 'state_initial_equations': True}
model = transfer_model(class_name, file_paths, compiler_options=opts)
init_fmu = load_fmu(compile_fmu(class_name, file_paths, compiler_options=opts))

# Create input data
# This would have worked if one input was not constant...
#~ columns = [0]
#~ columns += [sim_res.get_column(input_var.getName()) for input_var in model.getVariables(model.REAL_INPUT)]
#~ input = sim_res.get_data_matrix()[:, columns]
Example #20
0
def run_demo(with_plots=True, use_ma57=True, latex_plots=False):
    """
    This example is based on a binary distillation column. The model has 42
    states, 1083 algebraic variables and 2 control variables. The task is to
    get back to the desired steady-state after a short reflux breakdown.
    
    The example consists of the following steps:
    
    1.  Find the desired steady state by simulating ad infinitum with constant
        inputs.
    
    2.  Simulate the short reflux breakdown.

    3.  Simulate post-breakdown with constant inputs to generate an initial
        guess.

    4.  Solve the optimal control problem to get back to the desired steady
        state after the breakdown.
       
    5.  Verify the optimal trajectories by simulation.
    
    The model was developed in Moritz Diehl's PhD thesis:
    
    @PHDTHESIS{diehl2002phd,
      author = {Diehl, Moritz},
      title = {Real-Time Optimization for Large Scale Nonlinear Processes},
      school = {Heidelberg University},
      year = {2002},
      type = {Ph.{D}. thesis}
    }

    The Modelica implementation was based on the MATLAB implementation from
    John Hedengren's nonlinear model library available at:

    http://www.hedengren.net/research/models.htm

    This example needs one of the linear solvers MA27 or MA57 to work.
    The precense of MA27 or MA57 is not detected in the example, so if only 
    MA57 is present, then True must be passed in the use_ma57 argument.
    """
    ### 1. Find the desired steady state by simulating with constant inputs
    # Compile model
    file_name = (os.path.join(get_files_path(), "JMExamples.mo"),
                 os.path.join(get_files_path(), "JMExamples_opt.mop"))
    ss_fmu = compile_fmu("JMExamples.Distillation.Distillation4",
                         file_name)
    ss_model = load_fmu(ss_fmu)

    # Set constant input and simulate
    [L_vol_ref] = ss_model.get('Vdot_L1_ref')
    [Q_ref] = ss_model.get('Q_elec_ref')
    ss_res = ss_model.simulate(final_time=500000.,
                               input=(['Q_elec', 'Vdot_L1'],
                                      lambda t: [Q_ref, L_vol_ref]))

    # Extract results
    ss_T_14 = ss_res['Temp[28]']
    T_14_ref = ss_T_14[-1]
    ss_T_28 = ss_res['Temp[14]']
    T_28_ref = ss_T_28[-1]
    ss_L_vol = ss_res['Vdot_L1']
    ss_Q = ss_res['Q_elec']
    ss_t = ss_res['time']
    abs_zero = ss_model.get('absolute_zero')
    L_fac = 1e3 * 3.6e3
    Q_fac = 1e-3

    print(('T_14_ref: %.6f' % T_14_ref))
    print(('T_28_ref: %.6f' % T_28_ref))

    # Plot simulation
    if with_plots:
        # Plotting options
        plt.rcParams.update(
            {'font.serif': ['Times New Roman'],
             'text.usetex': latex_plots,
             'font.family': 'serif',
             'axes.labelsize': 20,
             'legend.fontsize': 16,
             'xtick.labelsize': 12,
             'font.size': 20,
             'ytick.labelsize': 14})
        pad = 2
        padplus = plt.rcParams['axes.labelsize'] / 2

        # Define function for custom axis scaling in plots
        def scale_axis(figure=plt, xfac=0.01, yfac=0.05):
            """
            Adjust the axis.

            The size of the axis is first changed to plt.axis('tight') and then
            scaled by (1 + xfac) horizontally and (1 + yfac) vertically.
            """
            (xmin, xmax, ymin, ymax) = figure.axis('tight')
            if figure == plt:
                figure.xlim(xmin - xfac * (xmax - xmin), xmax + xfac * (xmax - xmin))
                figure.ylim(ymin - yfac * (ymax - ymin), ymax + yfac * (ymax - ymin))
            else:
                figure.set_xlim(xmin - xfac * (xmax - xmin), xmax + xfac * (xmax - xmin))
                figure.set_ylim(ymin - yfac * (ymax - ymin), ymax + yfac * (ymax - ymin))

        # Define function for plotting the important quantities
        def plot_solution(t, T_28, T_14, Q, L_vol, fig_index, title):
            plt.close(fig_index)
            fig = plt.figure(fig_index)
            fig.subplots_adjust(wspace=0.35)

            ax = fig.add_subplot(2, 2, 1)
            bx = fig.add_subplot(2, 2, 2)
            cx = fig.add_subplot(2, 2, 3, sharex=ax)
            dx = fig.add_subplot(2, 2, 4, sharex=bx)
            width = 3

            ax.plot(t, T_28 + abs_zero, lw=width)
            ax.hold(True)
            ax.plot(t[[0, -1]], 2 * [T_28_ref + abs_zero], 'g--')
            ax.hold(False)
            ax.grid()
            if latex_plots:
                label = '$T_{28}$ [$^\circ$C]'
            else:
                label = 'T28'
            ax.set_ylabel(label, labelpad=pad)
            plt.setp(ax.get_xticklabels(), visible=False)
            scale_axis(ax)

            bx.plot(t, T_14 + abs_zero, lw=width)
            bx.hold(True)
            bx.plot(t[[0, -1]], 2 * [T_14_ref + abs_zero], 'g--')
            bx.hold(False)
            bx.grid()
            if latex_plots:
                label = '$T_{14}$ [$^\circ$C]'
            else:
                label = 'T14'
            ax.set_ylabel(label, labelpad=pad)
            plt.setp(bx.get_xticklabels(), visible=False)
            scale_axis(bx)

            cx.plot(t, Q * Q_fac, lw=width)
            cx.hold(True)
            cx.plot(t[[0, -1]], 2 * [Q_ref * Q_fac], 'g--')
            cx.hold(False)
            cx.grid()
            if latex_plots:
                ylabel = '$Q$ [kW]'
                xlabel = '$t$ [s]'
            else:
                ylabel = 'Q'
                xlabel = 't'
            cx.set_ylabel(ylabel, labelpad=pad)
            cx.set_xlabel(xlabel)
            scale_axis(cx)

            dx.plot(t, L_vol * L_fac, lw=width)
            dx.hold(True)
            dx.plot(t[[0, -1]], 2 * [L_vol_ref * L_fac], 'g--')
            dx.hold(False)
            dx.grid()
            if latex_plots:
                ylabel = '$L_{\Large \mbox{vol}}$ [l/h]'
                xlabel = '$t$ [s]'
            else:
                ylabel = 'L'
                xlabel = 't'
            dx.set_ylabel(ylabel, labelpad=pad)
            dx.set_xlabel(xlabel)
            scale_axis(dx)

            fig.suptitle(title)
            plt.show()

        # Call plot function
        plot_solution(ss_t, ss_T_28, ss_T_14, ss_Q, ss_L_vol, 1,
                      'Simulated trajectories to find steady state')

        # Plot steady state temperatures
        plt.close(2)
        plt.figure(2)
        plt.hold(True)
        for i in range(1, 43):
            temperature = (ss_res.final('Temp[' + repr(i) + ']') +
                           ss_res.initial('absolute_zero'))
            plt.plot(temperature, 43 - i, 'ko')
        plt.title('Steady state temperatures')
        if latex_plots:
            label = '$T$ [$^\circ$C]'
        else:
            label = 'T'
        plt.xlabel(label)
        plt.ylabel('Tray index [1]')

    ### 2. Simulate the short reflux breakdown
    # Compile model
    model_fmu = compile_fmu("JMExamples.Distillation.Distillation4", file_name)
    break_model = load_fmu(model_fmu)

    # Set initial values
    break_model.set('Q_elec_ref', Q_ref)
    break_model.set('Vdot_L1_ref', L_vol_ref)
    for i in range(1, 43):
        break_model.set('xA_init[%d]' % i, ss_res.final('xA[%d]' % i))

    # Define input function for broken reflux
    def input_function(time):
        if time < 700.:
            return [Q_ref, L_vol_ref]
        else:
            return [Q_ref, 0.5 / 1000. / 3600.]

    # Simulate and extract results
    break_res = break_model.simulate(
        final_time=1000., input=(['Q_elec', 'Vdot_L1'], input_function))
    break_T_14 = break_res['Temp[28]']
    break_T_28 = break_res['Temp[14]']
    break_L_vol = break_res['Vdot_L1']
    break_Q = break_res['Q_elec']
    break_t = break_res['time']

    # Plot simulation
    if with_plots:
        plot_solution(break_t, break_T_28, break_T_14, break_Q, break_L_vol, 3,
                      'Simulated short reflux breakdown')

    ### 3. Simulate post-breakdown with constant inputs to find initial guess
    # Compile the model
    ref_model = load_fmu(model_fmu)

    # Set initial conditions for post breakdown
    ref_model.set('Q_elec_ref', Q_ref)
    ref_model.set('Vdot_L1_ref', L_vol_ref)
    for i in range(1, 43):
        ref_model.set('xA_init[' + repr(i) + ']',
                      break_res.final('xA[' + repr(i) + ']'))

    # Simulate
    ref_res = ref_model.simulate(final_time=5000.,
                                 input=(['Q_elec', 'Vdot_L1'],
                                        lambda t: [Q_ref, L_vol_ref]))

    # Extract results
    ref_T_14 = ref_res['Temp[28]']
    ref_T_28 = ref_res['Temp[14]']
    ref_L_vol = ref_res['Vdot_L1']
    ref_Q = ref_res['Q_elec']
    ref_t = ref_res['time']

    # Plot initial guess
    if with_plots:
        plot_solution(ref_t, ref_T_28, ref_T_14, ref_Q, ref_L_vol, 4,
                      'Initial guess')

    ### 4. Solve optimal control problem
    # Compile optimization problem
    compiler_options={"common_subexp_elim":False}
    op = transfer_optimization_problem("JMExamples_opt.Distillation4_Opt",
                                       file_name, compiler_options)

    # Set initial conditions for post breakdown
    op.set('Q_elec_ref', Q_ref)
    op.set('Vdot_L1_ref', L_vol_ref)
    for i in range(1, 43):
        op.set('xA_init[' + repr(i) + ']', break_res.final('xA[' + repr(i) + ']'))

    # Set optimization options and solve
    opts = op.optimize_options()
    opts['init_traj'] = ref_res
    opts['nominal_traj'] = ref_res
    opts['n_e'] = 15
    opts['IPOPT_options']['linear_solver'] = "ma57" if use_ma57 else "ma27"
    opts['IPOPT_options']['mu_init'] = 1e-3
    opt_res = op.optimize(options=opts)

    # Extract results
    opt_T_14 = opt_res['Temp[28]']
    opt_T_28 = opt_res['Temp[14]']
    opt_L_vol = opt_res['Vdot_L1']
    opt_Q = opt_res['Q_elec']
    opt_t = opt_res['time']

    # Plot
    if with_plots:
        plot_solution(opt_t, opt_T_28, opt_T_14, opt_Q, opt_L_vol, 5,
                      'Optimal control')

    # Verify cost for testing purposes
    try:
        import casadi
    except:
        pass
    else:
        cost = float(opt_res.solver.solver_object.output(casadi.NLP_SOLVER_F))
        N.testing.assert_allclose(cost, 4.611038777467e-02, rtol=1e-2)

    ### 5. Verify optimization discretization by simulation
    verif_model = load_fmu(model_fmu)

    # Set initial conditions for post breakdown
    verif_model.set('Q_elec_ref', Q_ref)
    verif_model.set('Vdot_L1_ref', L_vol_ref)
    for i in range(1, 43):
        verif_model.set('xA_init[' + repr(i) + ']',
                        break_res.final('xA[' + repr(i) + ']'))

    # Simulate with optimal input
    verif_res = verif_model.simulate(final_time=5000.,
                                     input=opt_res.get_opt_input())

    # Extract results
    verif_T_14 = verif_res['Temp[28]']
    verif_T_28 = verif_res['Temp[14]']
    verif_L_vol = verif_res['Vdot_L1']
    verif_Q = verif_res['Q_elec']
    verif_t = verif_res['time']

    # Plot verifying simulation
    if with_plots:
        plot_solution(verif_t, verif_T_28, verif_T_14, verif_Q, verif_L_vol, 6,
                      'Simulation with optimal input')
#~ formatter = matplotlib.ticker.ScalarFormatter(useOffset=False)
formatter = matplotlib.ticker.ScalarFormatter()
#~ formatter.set_powerlimits((-2,2))

problem = ["simple", "circuit", "vehicle", "double_pendulum", "ccpp", "dist4"][4]
source = ["Modelica", "strings"][0]
with_plots = True
with_plots = False
#~ blt = True
#~ blt = False
#~ full_blt = True

if source != "Modelica":
	raise ValueError
class_name = "CombinedCycleStartup.Startup6Reference"
file_paths = (os.path.join(get_files_path(), "CombinedCycle.mo"),
			  os.path.join(get_files_path(), "CombinedCycleStartup.mop"))
opts = {'generate_html_diagnostics': True}
model_fmu = load_fmu(compile_fmu(class_name, file_paths, compiler_options=opts))
final_time = 5000.
opts = model_fmu.simulate_options()
opts['CVode_options']['rtol'] = 1e-10
opts['CVode_options']['atol'] = 1e-10
sim_res = model_fmu.simulate(final_time=final_time, options=opts)

eps = 1e-8
for i in xrange(2):
	if i == 0:
		linear_solver = "symbolicqr"
		title = "Symbolic QR"
	elif i == 1:
def run_demo(with_plots=True):
    """
    This example is based on a combined cycle power plant (CCPP). The model has
    9 states, 128 algebraic variables and 1 control variable. The task is to
    minimize the time required to perform a warm start-up of the power plant.
    This problem has become highly industrially relevant during the last few
    years, due to an increasing need to improve power generation flexibility.
    
    The example consists of the following steps:
    
    1.  Simulating the system using a simple input trajectory.
    
    2.  Solving the optimal control problem using the result from the first
        step to initialize the non-linear program. In addition, a set of 
        algebraic variables is eliminated by means of BLt information
       
    3.  Verifying the result from the second step by simulating the system
        once more usng the optimized input trajectory.
    
    The model was developed by Francesco Casella and is published in
    @InProceedings{CFA2011,
      author = "Casella, Francesco and Donida, Filippo and {\AA}kesson, Johan",
      title = "Object-Oriented Modeling and Optimal Control: A Case Study in
               Power Plant Start-Up",
      booktitle = "18th IFAC World Congress",
      address = "Milano, Italy",
      year = 2011,
      month = aug
    }
    """
    ### 1. Compute initial guess trajectories by means of simulation
    # Locate the Modelica and Optimica code
    file_paths = (os.path.join(get_files_path(), "CombinedCycle.mo"),
                  os.path.join(get_files_path(), "CombinedCycleStartup.mop"))

    # Compile the optimization initialization model
    init_sim_fmu = compile_fmu("CombinedCycleStartup.Startup6Reference",
                               file_paths,
                               separate_process=True)

    # Load the model
    init_sim_model = load_fmu(init_sim_fmu)

    # Simulate
    init_res = init_sim_model.simulate(start_time=0., final_time=10000.)

    # Extract variable profiles
    init_sim_plant_p = init_res['plant.p']
    init_sim_plant_sigma = init_res['plant.sigma']
    init_sim_plant_load = init_res['plant.load']
    init_sim_time = init_res['time']

    # Plot the initial guess trajectories
    if with_plots:
        plt.close(1)
        plt.figure(1)
        plt.subplot(3, 1, 1)
        plt.plot(init_sim_time, init_sim_plant_p * 1e-6)
        plt.ylabel('evaporator pressure [MPa]')
        plt.grid(True)
        plt.title('Initial guess obtained by simulation')

        plt.subplot(3, 1, 2)
        plt.plot(init_sim_time, init_sim_plant_sigma * 1e-6)
        plt.grid(True)
        plt.ylabel('turbine thermal stress [MPa]')

        plt.subplot(3, 1, 3)
        plt.plot(init_sim_time, init_sim_plant_load)
        plt.grid(True)
        plt.ylabel('input load [1]')
        plt.xlabel('time [s]')

    ### 2. Solve the optimal control problem
    # Compile model
    from pyjmi import transfer_to_casadi_interface
    compiler_options = {'equation_sorting': True, "common_subexp_elim": False}
    op = transfer_to_casadi_interface("CombinedCycleStartup.Startup6",
                                      file_paths, compiler_options)

    # Set options
    opt_opts = op.optimize_options()
    opt_opts['n_e'] = 50  # Number of elements
    opt_opts['init_traj'] = init_res  # Simulation result
    opt_opts['nominal_traj'] = init_res

    # variable elimination
    eliminables = op.getEliminableVariables()
    algebraics = op.getVariables(op.REAL_ALGEBRAIC)
    print "Number of algebraics:  ", len(algebraics)

    print "Eliminating variables!"

    eliminable_algebraics = [a for a in algebraics if a in eliminables]
    variables_to_eliminate = list()
    variables_with_bounds = list()
    for v in eliminable_algebraics:
        if not v.hasAttributeSet("min") and not v.hasAttributeSet("max"):
            variables_to_eliminate.append(v)
        else:
            variables_with_bounds.append(v)

    # Elimination of unbounded variables
    op.markVariablesForElimination(variables_to_eliminate)
    # Elimination of bounded variables (skip elimination of plant.sigma)
    bounded_eliminations = [
        v for v in variables_with_bounds if not v.getName() == "plant.sigma"
    ]
    op.markVariablesForElimination(bounded_eliminations)
    op.eliminateVariables()

    # Alternative way of eliminating variables however this method do not eliminate any bounded variables
    #op.eliminateAlgebraics()

    print "Done with elimination"
    eliminated_vars = op.getEliminatedVariables()
    print "Number of variables that were eliminated: ", len(eliminated_vars)

    # Solve the optimal control problem
    opt_res = op.optimize(options=opt_opts)

    # get output of one eliminated variable
    elim_var_name = eliminable_algebraics[5].getName()

    # Extract variable profiles
    opt_plant_p = opt_res['plant.p']
    opt_plant_sigma = opt_res['plant.sigma']
    opt_plant_load = opt_res['plant.load']
    opt_eliminated = opt_res[elim_var_name]
    opt_time = opt_res['time']
    opt_input = N.vstack([opt_time, opt_plant_load]).T

    # Plot the optimized trajectories
    if with_plots:
        plt.close(2)
        plt.figure(2)
        plt.subplot(4, 1, 1)
        plt.plot(opt_time, opt_plant_p * 1e-6)
        plt.ylabel('evaporator pressure [MPa]')
        plt.grid(True)
        plt.title('Optimized trajectories')

        plt.subplot(4, 1, 2)
        plt.plot(opt_time, opt_plant_sigma * 1e-6)
        plt.grid(True)
        plt.ylabel('turbine thermal stress [MPa]')

        plt.subplot(4, 1, 3)
        plt.plot(opt_time, opt_plant_load)
        plt.grid(True)
        plt.ylabel('input load [1]')
        plt.xlabel('time [s]')

        plt.subplot(4, 1, 4)
        plt.plot(opt_time, opt_eliminated)
        plt.grid(True)
        plt.ylabel(elim_var_name)
        plt.xlabel('time [s]')

    # Verify solution for testing purposes
    try:
        import casadi
    except:
        pass
    else:
        cost = float(opt_res.solver.solver_object.output(casadi.NLP_SOLVER_F))
        N.testing.assert_allclose(cost, 17492.465548193624, rtol=1e-5)

    ### 3. Simulate to verify the optimal solution
    # Compile model
    sim_fmu = compile_fmu("CombinedCycle.Optimization.Plants.CC0D_WarmStartUp",
                          file_paths)

    # Load model
    sim_model = load_fmu(sim_fmu)

    # Simulate using optimized input
    sim_res = sim_model.simulate(start_time=0.,
                                 final_time=4000.,
                                 input=('load', opt_input))

    # Extract variable profiles
    sim_plant_p = sim_res['p']
    sim_plant_sigma = sim_res['sigma']
    sim_plant_load = sim_res['load']
    sim_time = sim_res['time']

    # Plot the simulated trajectories
    if with_plots:
        plt.close(3)
        plt.figure(3)
        plt.subplot(3, 1, 1)
        plt.plot(opt_time, opt_plant_p * 1e-6, '--', lw=5)
        plt.hold(True)
        plt.plot(sim_time, sim_plant_p * 1e-6, lw=2)
        plt.ylabel('evaporator pressure [MPa]')
        plt.grid(True)
        plt.legend(('optimized', 'simulated'), loc='lower right')
        plt.title('Verification')

        plt.subplot(3, 1, 2)
        plt.plot(opt_time, opt_plant_sigma * 1e-6, '--', lw=5)
        plt.hold(True)
        plt.plot(sim_time, sim_plant_sigma * 1e-6, lw=2)
        plt.ylabel('turbine thermal stress [MPa]')
        plt.grid(True)

        plt.subplot(3, 1, 3)
        plt.plot(opt_time, opt_plant_load, '--', lw=5)
        plt.hold(True)
        plt.plot(sim_time, sim_plant_load, lw=2)
        plt.ylabel('input load [1]')
        plt.xlabel('time [s]')
        plt.grid(True)

        plt.show()

    # Verify solution for testing purposes
    N.testing.assert_allclose(opt_res.final('plant.p'),
                              sim_res.final('p'),
                              rtol=5e-3)
def run_demo(with_plots=True):
    """
    This example is based on the Hicks-Ray Continuously Stirred Tank 
    Reactors (CSTR) system. The system has two states, the 
    concentration and the temperature. The control input to the system 
    is the temperature of the cooling flow in the reactor jacket. The 
    chemical reaction in the reactor is exothermic, and also 
    temperature dependent; high temperature results in high reaction 
    rate.
    
    This example serves to illustrate how constraints can be added 
    when using the CasADi-based Moving Horizon Estimator (MHE). 
    Shows the importance of constraints when working close to a 
    physical constraint by comparing the unconstrained MHE with 
    the constrained one.
    
    Constraints are added by simply extending a Modelica or Optimica 
    model and adding the constraint or by creating a Constraint to 
    the OptimizationProblem object using setPathConstraints. 
    The usage of point constraints is not supported and can give 
    unpredictable results.
    """
    #Get the name and location of the Modelica package
    file_path = os.path.join(get_files_path(), "CSTR.mop")

    #Transfer the unconstrained OptimizationProblem from the model
    #using "state_initial_equations" and "accept_model"
    unconstr_op = transfer_optimization_problem(
        'CSTR.CSTR_mhe_model',
        file_path,
        accept_model=True,
        compiler_options={"state_initial_equations": True})
    #Transfer the constrained OptimizationProblem from the Optimica model
    #using "state_initial_equations"
    constr_op = transfer_optimization_problem(
        'CSTR.CSTR_mhe',
        file_path,
        accept_model=False,
        compiler_options={"state_initial_equations": True})
    #The constraint could instead have been added using the following:
    #c_var = op.getVariable('c').getVar()
    #constr = mc.Constraint(c_var, MX(0), mc.Constraint.GEQ)
    #op.setPathConstraints([constr])

    #Compile the FMU with the same option as for the OptimizationProblem
    fmu = compile_fmu('CSTR.CSTR_mhe_model',
                      file_path,
                      compiler_options={"state_initial_equations": True})
    #Load the FMU
    model = load_fmu(fmu)

    #Define the time interval and the number of points
    sim_time = 3.
    nbr_of_points = 31
    #Calculate the corresponding sample time
    sample_time = sim_time / (nbr_of_points - 1)

    #Create an array of the time points
    time = N.linspace(0., sim_time, nbr_of_points)

    ###Create noise for the measurement data
    #Create the discrete covariance matrices
    Q = N.array([[20.]])
    R = N.array([[10., 0.], [0., 1.]])
    #The expectations
    w_my = N.array([0.])
    v_my = N.array([0., 0.])
    ##Get the noise sequences
    #Process noise
    #Use same seed for consistent results
    N.random.seed(3)
    w = N.transpose(N.random.multivariate_normal(w_my, Q, nbr_of_points))
    #Measurement noise
    N.random.seed(188)
    v = N.transpose(N.random.multivariate_normal(v_my, R, nbr_of_points))

    ###Chose a control signal
    u = 350. * N.ones(nbr_of_points)
    ###Define the inputs for the MHE object
    ##See the documentation of the MHEOptions for more details
    #Create the options object
    MHE_opts = MHEOptions()
    #Process noise covariance
    MHE_opts['process_noise_cov'] = [('Tc', 200.)]
    #The names of the input signals acting as control signals
    MHE_opts['input_names'] = ['Tc']
    #Chose what variables are measured and their covariance structure
    #The two definitions below are equivalent
    MHE_opts['measurement_cov'] = [('c', 1.), ('T', 0.1)]
    MHE_opts['measurement_cov'] = [(['c', 'T'], N.array([[1., 0.0], [0.0,
                                                                     0.1]]))]
    #Error covariance matrix
    MHE_opts['P0_cov'] = [('c', 10.), ('T', 5.)]

    ##The initial guess of the states
    x_0_guess = dict([('c', 0.), ('T', 352.)])
    #Initial value of the simulation
    x_0 = dict([('c', 0.), ('T', 350.)])

    ##Use mhe_initial_values module or some equivalent method to get the
    #initial values of the state derivatives and the algebraic variables
    #Control signal for time step zero
    u_0 = {'Tc': u[0]}

    (dx_0, c_0) = initv.optimize_for_initial_values(unconstr_op, x_0_guess,
                                                    u_0, MHE_opts)

    #Decide the horizon length
    horizon = 8

    ##Create the MHE objects
    unconstr_MHE_object = MHE(unconstr_op, sample_time, horizon, x_0_guess,
                              dx_0, c_0, MHE_opts)
    constr_MHE_object = MHE(constr_op, sample_time, horizon, x_0_guess, dx_0,
                            c_0, MHE_opts)
    #Create a structure for saving the estimates
    unconstr_x_est = {'c': [x_0_guess['c']], 'T': [x_0_guess['T']]}
    constr_x_est = {'c': [x_0_guess['c']], 'T': [x_0_guess['T']]}
    #Create a structure for saving the simulated data
    x = {'c': [x_0['c']], 'T': [x_0['T']]}
    #Create the structure for the measured data
    y = {'c': [], 'T': []}
    #Loop over estimation and simulation
    for t in range(1, nbr_of_points):
        #Create the measurement data from the simulated data and added noise
        y['c'].append(x['c'][-1] + v[0, t - 1])
        y['T'].append(x['T'][-1] + v[1, t - 1])
        #Create list of tuples with (name, measurement) structure
        y_t = [('c', y['c'][-1]), ('T', y['T'][-1])]
        #Create list of tuples with (name, input) structure
        u_t = [('Tc', u[t - 1])]
        #Estimate
        constr_x_est_t = constr_MHE_object.step(u_t, y_t)
        unconstr_x_est_t = unconstr_MHE_object.step(u_t, y_t)
        #Add the results to x_est
        for key in constr_x_est.keys():
            constr_x_est[key].append(constr_x_est_t[key])
        for key in unconstr_x_est.keys():
            unconstr_x_est[key].append(unconstr_x_est_t[key])
        ###Prepare the simulation
        #Create the input object
        u_traj = N.transpose(N.vstack((0., u[t])))
        input_object = ('Tc', u_traj)

        #Set the initial values of the states
        for (key, list) in x.items():
            model.set('_start_' + key, list[-1])

        #Simulate with one communication point to get the
        #value at the right point
        res = model.simulate(final_time=sample_time,
                             input=input_object,
                             options={'ncp': 1})

        #Extract the state values from the result object
        for key in x.keys():
            x[key].append(res[key][-1])
        #reset the FMU
        model.reset()

    #Add the last measurement
    y['c'].append(x['c'][-1] + v[0, -1])
    y['T'].append(x['T'][-1] + v[1, -1])

    if with_plots:
        plt.close('MHE')
        plt.figure('MHE')
        plt.subplot(2, 1, 1)
        plt.plot(time, constr_x_est['c'])
        plt.plot(time, unconstr_x_est['c'])
        plt.plot(time, x['c'], ls='--', color='k')
        plt.plot(time, y['c'], ls='-', marker='+', mfc='k', mec='k', mew=1.)
        plt.legend(('Constrained concentration estimate',
                    'Unconstrained concentration estimate',
                    'Simulated concentration', 'Measured concentration'))
        plt.grid()
        plt.ylabel('Concentration')

        plt.subplot(2, 1, 2)
        plt.plot(time, constr_x_est['T'])
        plt.plot(time, unconstr_x_est['T'])
        plt.plot(time, x['T'], ls='--', color='k')
        plt.plot(time, y['T'], ls='-', marker='+', mfc='k', mec='k', mew=1.)
        plt.legend(('Constrained temperature estimate',
                    'Unconstrained temperature estimate',
                    'Simulated temperature', 'Measured temperature'))
        plt.grid()
        plt.ylabel('Temperature')

        plt.show()
Example #24
0
        opt_opts['IPOPT_options']['acceptable_constr_viol_tol'] = 1e-12
        opt_opts['IPOPT_options']['acceptable_dual_inf_tol'] = 1e-12
        opt_opts['IPOPT_options']['acceptable_compl_inf_tol'] = 1e-12
        opt_opts['IPOPT_options']['linear_solver'] = "ma57"
        opt_opts['IPOPT_options']['ma57_pivtol'] = 1e-4
        opt_opts['IPOPT_options']['ma27_pivtol'] = 1e-4
        opt_opts['IPOPT_options']['ma97_u'] = 1e-4
        opt_opts['IPOPT_options']['ma97_umax'] = 1e-2
        opt_opts['IPOPT_options']['ma57_automatic_scaling'] = "yes"
        opt_opts['IPOPT_options']['mu_strategy'] = "adaptive"
        if problem == "vehicle":
            std_dev[problem] = 0.1
            caus_opts = sp.CausalizationOptions()
            caus_opts['uneliminable'] = ['car.Fxf', 'car.Fxr', 'car.Fyf', 'car.Fyr']
            class_name = "Turn"
            file_paths = os.path.join(get_files_path(), "vehicle_turn.mop")
            init_res = LocalDAECollocationAlgResult(result_data=ResultDymolaTextual('vehicle_sol.txt'))
            opt_opts['init_traj'] = init_res
            opt_opts['nominal_traj'] = init_res
            opt_opts['IPOPT_options']['max_cpu_time'] = 30
            opt_opts['n_e'] = 60

            # Set blocking factors
            factors = {'delta_u': opt_opts['n_e'] / 2 * [2],
                       'Twf_u': opt_opts['n_e'] / 4 * [4],
                       'Twr_u': opt_opts['n_e'] / 4 * [4]}
            rad2deg = 180. / (2*np.pi)
            du_bounds = {'delta_u': 2. / rad2deg}
            bf = BlockingFactors(factors, du_bounds=du_bounds)
            opt_opts['blocking_factors'] = bf
Example #25
0
def run_demo(with_plots=True):
    """
    This example is based on the Hicks-Ray Continuously Stirred Tank Reactors 
    (CSTR) system. The system has two states, the concentration and the 
    temperature. The control input to the system is the temperature of the 
    cooling flow in the reactor jacket. The chemical reaction in the reactor is 
    exothermic, and also temperature dependent; high temperature results in high 
    reaction rate.
    
    The problem is solved using the CasADi-based collocation algorithm. The
    steps performed correspond to those demonstrated in
    example pyjmi.examples.cstr, where the same problem is solved using the
    default JMI algorithm. FMI is used for initialization and simulation
    purposes.
    
    The following steps are demonstrated in this example:
    
    1.  How to solve the initialization problem. The initialization model has
        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. Point A corresponds to
        operating conditions where the reactor is cold and the reaction rate is
        low, whereas point B corresponds to a higher temperature where the
        reaction rate is high.
    
    2.  How to generate an initial guess for a direct collocation method by
        means of simulation with a constant input. The trajectories resulting
        from the simulation are used to initialize the variables in the
        transcribed NLP.
       
    3.  An optimal control problem is solved where the objective is to transfer 
        the state of the system from stationary point A to point B. The
        challenge is to ignite the reactor while avoiding uncontrolled
        temperature increase.

    4.  Finally the system is simulated using the optimal control profile. This
        step is important in order to verify that the approximation in the
        transcription step is sufficiently accurate.
    """
    ### 1. Solve the initialization problem
    # Locate the Modelica and Optimica code
    file_path = os.path.join(get_files_path(), "CSTR.mop")
    
    # Compile the stationary initialization model into an FMU
    init_fmu = compile_fmu("CSTR.CSTR_Init", file_path)
    
    # Load the FMU
    init_model = load_fmu(init_fmu)
    
    # Set input for Stationary point A
    Tc_0_A = 250
    init_model.set('Tc', Tc_0_A)

    # Solve the initialization problem using FMI
    init_model.initialize()

    # Store stationary point A
    [c_0_A, T_0_A] = init_model.get(['c', 'T'])

    # Print some data for stationary point A
    print(' *** Stationary point A ***')
    print('Tc = %f' % Tc_0_A)
    print('c = %f' % c_0_A)
    print('T = %f' % T_0_A)
    
    # Set inputs for Stationary point B
    init_model.reset() # reset the FMU so that we can initialize it again
    Tc_0_B = 280
    init_model.set('Tc', Tc_0_B)

    # Solve the initialization problem using FMI
    init_model.initialize()

    # Store stationary point B
    [c_0_B, T_0_B] = init_model.get(['c', 'T'])

    # Print some data for stationary point B
    print(' *** Stationary point B ***')
    print('Tc = %f' % Tc_0_B)
    print('c = %f' % c_0_B)
    print('T = %f' % T_0_B)
    
    ### 2. Compute initial guess trajectories by means of simulation
    # Compile the optimization initialization model
    init_sim_fmu = compile_fmu("CSTR.CSTR_Init_Optimization", file_path)

    # Load the model
    init_sim_model = load_fmu(init_sim_fmu)
    
    # Set initial and reference values
    init_sim_model.set('cstr.c_init', c_0_A)
    init_sim_model.set('cstr.T_init', T_0_A)
    init_sim_model.set('c_ref', c_0_B)
    init_sim_model.set('T_ref', T_0_B)
    init_sim_model.set('Tc_ref', Tc_0_B)
    
    # Simulate with constant input Tc
    init_res = init_sim_model.simulate(start_time=0., final_time=150.)

    # Extract variable profiles
    t_init_sim = init_res['time']
    c_init_sim = init_res['cstr.c']
    T_init_sim = init_res['cstr.T']
    Tc_init_sim = init_res['cstr.Tc'] + N.zeros(t_init_sim.shape) # make Tc_init_sim be a vector

    # Plot the initial guess trajectories
    if with_plots:
        plt.close(1)
        plt.figure(1)
        plt.hold(True)
        plt.subplot(3, 1, 1)
        plt.plot(t_init_sim, c_init_sim)
        plt.grid()
        plt.ylabel('Concentration')
        plt.title('Initial guess obtained by simulation')

        plt.subplot(3, 1, 2)
        plt.plot(t_init_sim, T_init_sim)
        plt.grid()
        plt.ylabel('Temperature')

        plt.subplot(3, 1, 3)
        plt.plot(t_init_sim, Tc_init_sim)
        plt.grid()
        plt.ylabel('Cooling temperature')
        plt.xlabel('time')
        plt.show()
    
    ### 3. Solve the optimal control problem
    # Compile and load optimization problem
    op = transfer_optimization_problem("CSTR.CSTR_Opt2", file_path)
    
    # Set reference values
    op.set('Tc_ref', Tc_0_B)
    op.set('c_ref', float(c_0_B))
    op.set('T_ref', float(T_0_B))
    
    # Set initial values
    op.set('cstr.c_init', float(c_0_A))
    op.set('cstr.T_init', float(T_0_A))
    
    # Set options
    opt_opts = op.optimize_options()
    opt_opts['n_e'] = 19 # Number of elements
    opt_opts['init_traj'] = init_res.result_data
    opt_opts['nominal_traj'] = init_res.result_data
    opt_opts['IPOPT_options']['tol'] = 1e-10
    
    # Solve the optimal control problem
    res = op.optimize(options=opt_opts)
    
    # Extract variable profiles
    c_res = res['cstr.c']
    T_res = res['cstr.T']
    Tc_res = res['cstr.Tc']
    time_res = res['time']

    c_ref = res['c_ref'][0] # extract constant value as first element
    T_ref = res['T_ref'][0]
    Tc_ref = res['Tc_ref'][0]
    
    # Verify solution for testing purposes
    try:
        import casadi
    except:
        pass
    else:
        cost = float(res.solver.solver.output(casadi.NLP_SOLVER_F))
        assert(N.abs(cost/1.e3 - 1.86162353098) < 1e-3)

    # Plot the results
    if with_plots:
        plt.close(2)
        plt.figure(2)
        plt.hold(True)
        plt.subplot(3, 1, 1)
        plt.plot(time_res, c_res)
        plt.plot([time_res[0], time_res[-1]], [c_ref, c_ref], '--')
        plt.grid()
        plt.ylabel('Concentration')
        plt.title('Optimized trajectories')

        plt.subplot(312)
        plt.plot(time_res,T_res)
        plt.plot([time_res[0],time_res[-1]],[T_ref,T_ref],'--')
        plt.grid()
        plt.ylabel('Temperature')

        plt.subplot(313)
        plt.plot(time_res,Tc_res)
        plt.plot([time_res[0],time_res[-1]],[Tc_ref,Tc_ref],'--')
        plt.grid()
        plt.ylabel('Cooling temperature')
        plt.xlabel('time')
        plt.show()

    ### 4. Simulate to verify the optimal solution
    # Compile model
    sim_fmu = compile_fmu("CSTR.CSTR", file_path)

    # Load model
    sim_model = load_fmu(sim_fmu)

    # Get optimized input
    (_, opt_input) = res.solver.get_opt_input()
    
    # Set initial values
    sim_model.set('c_init', c_0_A)
    sim_model.set('T_init', T_0_A)

    # Simulate using optimized input
    sim_opts = sim_model.simulate_options()
    sim_opts['CVode_options']['rtol'] = 1e-6
    sim_opts['CVode_options']['atol'] = 1e-8
    res = sim_model.simulate(start_time=0., final_time=150.,
                             input=('Tc', opt_input), options=sim_opts)

    # Extract variable profiles
    c_sim = res['c']
    T_sim = res['T']
    Tc_sim = res['Tc']
    time_sim = res['time']

    # Verify results
    N.testing.assert_array_less(abs(c_res[-1] - c_sim[-1])/c_res[-1], 5e-1)

    # Plot the results
    if with_plots:
        plt.close(3)
        plt.figure(3)
        plt.hold(True)
        plt.subplot(3, 1, 1)
        plt.plot(time_res, c_res, '--')
        plt.plot(time_sim, c_sim)
        plt.legend(('optimized', 'simulated'))
        plt.grid(True)
        plt.ylabel('Concentration')
        plt.title('Verification')
        
        plt.subplot(3, 1, 2)
        plt.plot(time_res, T_res, '--')
        plt.plot(time_sim, T_sim)
        plt.grid(True)
        plt.ylabel('Temperature')
        
        plt.subplot(3, 1, 3)
        plt.plot(time_res, Tc_res, '--')
        plt.plot(time_sim, Tc_sim)
        plt.grid(True)
        plt.ylabel('Cooling temperature')
        plt.xlabel('time')
        plt.show()
def run_demo(with_plots=True):
    """
    This example solves the optimization problem from pyjmi.examples.ccpp using the Python-based symbolic elimination.
    """
    # Load initial gues
    init_path = os.path.join(get_files_path(), "ccpp_init.txt")
    init_res = LocalDAECollocationAlgResult(
        result_data=ResultDymolaTextual(init_path))

    # Compile model
    class_name = "CombinedCycleStartup.Startup6"
    file_paths = (os.path.join(get_files_path(), "CombinedCycle.mo"),
                  os.path.join(get_files_path(), "CombinedCycleStartup.mop"))
    compiler_options = {'equation_sorting': True, 'automatic_tearing': True}
    op = transfer_optimization_problem("CombinedCycleStartup.Startup6",
                                       file_paths, compiler_options)

    # Set elimination options
    elim_opts = EliminationOptions()
    elim_opts['ineliminable'] = ['plant.sigma']
    if with_plots:
        elim_opts['draw_blt'] = True

    # Eliminate algebraic variables
    op = BLTOptimizationProblem(op, elim_opts)

    # Set collocation options
    opt_opts = op.optimize_options()
    opt_opts['init_traj'] = init_res
    opt_opts['nominal_traj'] = init_res

    # Solve the optimal control problem
    opt_res = op.optimize(options=opt_opts)

    # Extract variable profiles
    opt_plant_p = opt_res['plant.p']
    opt_plant_sigma = opt_res['plant.sigma']
    opt_plant_load = opt_res['plant.load']
    opt_time = opt_res['time']

    # Plot the optimized trajectories
    if with_plots:
        plt.close(2)
        plt.figure(2)
        plt.subplot(3, 1, 1)
        plt.plot(opt_time, opt_plant_p * 1e-6)
        plt.ylabel('evaporator pressure [MPa]')
        plt.grid(True)
        plt.title('Optimized trajectories')

        plt.subplot(3, 1, 2)
        plt.plot(opt_time, opt_plant_sigma * 1e-6)
        plt.grid(True)
        plt.ylabel('turbine thermal stress [MPa]')

        plt.subplot(3, 1, 3)
        plt.plot(opt_time, opt_plant_load)
        plt.grid(True)
        plt.ylabel('input load [1]')
        plt.xlabel('time [s]')

    # Verify solution for testing purposes
    try:
        import casadi
    except:
        pass
    else:
        cost = float(opt_res.solver.solver_object.getOutput('f'))
        N.testing.assert_allclose(cost, 17492.465548193624, rtol=1e-5)
Example #27
0
def run_demo(with_plots=True):
    """
    This example is based on a combined cycle power plant (CCPP). The model has
    9 states, 128 algebraic variables and 1 control variable. The task is to
    minimize the time required to perform a warm start-up of the power plant.
    This problem has become highly industrially relevant during the last few
    years, due to an increasing need to improve power generation flexibility.
    
    The example consists of the following steps:
    
    1.  Simulating the system using a simple input trajectory.
    
    2.  Solving the optimal control problem using the result from the first
        step to initialize the non-linear program.
       
    3.  Verifying the result from the second step by simulating the system
        once more usng the optimized input trajectory.
    
    The model was developed by Francesco Casella and is published in
    @InProceedings{CFA2011,
      author = "Casella, Francesco and Donida, Filippo and {\AA}kesson, Johan",
      title = "Object-Oriented Modeling and Optimal Control: A Case Study in
               Power Plant Start-Up",
      booktitle = "18th IFAC World Congress",
      address = "Milano, Italy",
      year = 2011,
      month = aug
    }
    """
    ### 1. Compute initial guess trajectories by means of simulation
    # Locate the Modelica and Optimica code
    file_paths = (os.path.join(get_files_path(), "CombinedCycle.mo"),
                  os.path.join(get_files_path(), "CombinedCycleStartup.mop"))
    
    # Compile the optimization initialization model
    init_sim_fmu = compile_fmu("CombinedCycleStartup.Startup6Reference",
                               file_paths, separate_process=True)
    
    # Load the model
    init_sim_model = load_fmu(init_sim_fmu)
    
    # Simulate
    init_res = init_sim_model.simulate(start_time=0., final_time=10000.)
    
    # Extract variable profiles
    init_sim_plant_p = init_res['plant.p']
    init_sim_plant_sigma = init_res['plant.sigma']
    init_sim_plant_load = init_res['plant.load']
    init_sim_time = init_res['time']
    
    # Plot the initial guess trajectories
    if with_plots:
        plt.close(1)
        plt.figure(1)
        plt.subplot(3, 1, 1)
        plt.plot(init_sim_time, init_sim_plant_p * 1e-6)
        plt.ylabel('evaporator pressure [MPa]')
        plt.grid(True)
        plt.title('Initial guess obtained by simulation')
        
        plt.subplot(3, 1, 2)
        plt.plot(init_sim_time, init_sim_plant_sigma * 1e-6)
        plt.grid(True)
        plt.ylabel('turbine thermal stress [MPa]')
        
        plt.subplot(3, 1, 3)
        plt.plot(init_sim_time, init_sim_plant_load)
        plt.grid(True)
        plt.ylabel('input load [1]')
        plt.xlabel('time [s]')
    
    ### 2. Solve the optimal control problem
    # Compile model
    from pyjmi import transfer_to_casadi_interface
    op = transfer_to_casadi_interface("CombinedCycleStartup.Startup6",
                                      file_paths)
    
    # Set options
    opt_opts = op.optimize_options()
    opt_opts['n_e'] = 50 # Number of elements
    opt_opts['init_traj'] = init_res.result_data # Simulation result
    opt_opts['nominal_traj'] = init_res.result_data
    
    # Solve the optimal control problem
    opt_res = op.optimize(options=opt_opts)
    
    # Extract variable profiles
    opt_plant_p = opt_res['plant.p']
    opt_plant_sigma = opt_res['plant.sigma']
    opt_plant_load = opt_res['plant.load']
    opt_time = opt_res['time']
    opt_input = N.vstack([opt_time, opt_plant_load]).T
    
    # Plot the optimized trajectories
    if with_plots:
        plt.close(2)
        plt.figure(2)
        plt.subplot(3, 1, 1)
        plt.plot(opt_time, opt_plant_p * 1e-6)
        plt.ylabel('evaporator pressure [MPa]')
        plt.grid(True)
        plt.title('Optimized trajectories')
        
        plt.subplot(3, 1, 2)
        plt.plot(opt_time, opt_plant_sigma * 1e-6)
        plt.grid(True)
        plt.ylabel('turbine thermal stress [MPa]')
        
        plt.subplot(3, 1, 3)
        plt.plot(opt_time, opt_plant_load)
        plt.grid(True)
        plt.ylabel('input load [1]')
        plt.xlabel('time [s]')
    
    # Verify solution for testing purposes
    try:
        import casadi
    except:
        pass
    else:
        cost = float(opt_res.solver.solver.output(casadi.NLP_SOLVER_F))
        N.testing.assert_allclose(cost, 17492.465548193624, rtol=1e-5)

    ### 3. Simulate to verify the optimal solution
    # Compile model
    sim_fmu = compile_fmu("CombinedCycle.Optimization.Plants.CC0D_WarmStartUp",
                          file_paths)

    # Load model
    sim_model = load_fmu(sim_fmu)
    
    # Simulate using optimized input
    sim_res = sim_model.simulate(start_time=0., final_time=4000.,
                                 input=('load', opt_input))
    
    # Extract variable profiles
    sim_plant_p = sim_res['p']
    sim_plant_sigma = sim_res['sigma']
    sim_plant_load = sim_res['load']
    sim_time = sim_res['time']
    
    # Plot the simulated trajectories
    if with_plots:
        plt.close(3)
        plt.figure(3)
        plt.subplot(3, 1, 1)
        plt.plot(opt_time, opt_plant_p * 1e-6, '--', lw=5)
        plt.hold(True)
        plt.plot(sim_time, sim_plant_p * 1e-6, lw=2)
        plt.ylabel('evaporator pressure [MPa]')
        plt.grid(True)
        plt.legend(('optimized', 'simulated'), loc='lower right')
        plt.title('Verification')
        
        plt.subplot(3, 1, 2)
        plt.plot(opt_time, opt_plant_sigma * 1e-6, '--', lw=5)
        plt.hold(True)
        plt.plot(sim_time, sim_plant_sigma * 1e-6, lw=2)
        plt.ylabel('turbine thermal stress [MPa]')
        plt.grid(True)
        
        plt.subplot(3, 1, 3)
        plt.plot(opt_time, opt_plant_load, '--', lw=5)
        plt.hold(True)
        plt.plot(sim_time, sim_plant_load, lw=2)
        plt.ylabel('input load [1]')
        plt.xlabel('time [s]')
        plt.grid(True)
        plt.show()
    
    # Verify solution for testing purposes
    N.testing.assert_allclose(opt_res.final('plant.p'),
                              sim_res.final('p'), rtol=5e-3)
Example #28
0
def run_demo(with_plots=True):
    """
    This example demonstrates how to solve parameter estimation problmes.

    The data used in the example was recorded by Kristian Soltesz at the 
    Department of Automatic Control. 
    """
    # Load measurement data from file
    data_path = os.path.join(get_files_path(), "qt_par_est_data.mat")
    data = loadmat(data_path, appendmat=False)

    # Extract data series
    t_meas = data['t'][6000::100, 0] - 60
    y1_meas = data['y1_f'][6000::100, 0] / 100
    y2_meas = data['y2_f'][6000::100, 0] / 100
    y3_meas = data['y3_d'][6000::100, 0] / 100
    y4_meas = data['y4_d'][6000::100, 0] / 100
    u1 = data['u1_d'][6000::100, 0]
    u2 = data['u2_d'][6000::100, 0]

    # Plot measurements and inputs
    if with_plots:
        plt.close(1)
        plt.figure(1)
        plt.subplot(2, 2, 1)
        plt.plot(t_meas, y3_meas)
        plt.title('x3')
        plt.grid()
        plt.subplot(2, 2, 2)
        plt.plot(t_meas, y4_meas)
        plt.title('x4')
        plt.grid()
        plt.subplot(2, 2, 3)
        plt.plot(t_meas, y1_meas)
        plt.title('x1')
        plt.xlabel('t[s]')
        plt.grid()
        plt.subplot(2, 2, 4)
        plt.plot(t_meas, y2_meas)
        plt.title('x2')
        plt.xlabel('t[s]')
        plt.grid()

        plt.close(2)
        plt.figure(2)
        plt.subplot(2, 1, 1)
        plt.plot(t_meas, u1)
        plt.hold(True)
        plt.title('u1')
        plt.grid()
        plt.subplot(2, 1, 2)
        plt.plot(t_meas, u2)
        plt.title('u2')
        plt.xlabel('t[s]')
        plt.hold(True)
        plt.grid()

    # Build input trajectory matrix for use in simulation
    u = N.transpose(N.vstack([t_meas, u1, u2]))

    # Compile and load FMU
    model_path = os.path.join(get_files_path(), "QuadTankPack.mop")
    fmu_name = compile_fmu('QuadTankPack.Sim_QuadTank', model_path)
    model = load_fmu(fmu_name)

    # Simulate model response with nominal parameter values
    res = model.simulate(input=(['u1', 'u2'], u),
                         start_time=0.,
                         final_time=60.)

    # Load simulation result
    x1_sim = res['qt.x1']
    x2_sim = res['qt.x2']
    x3_sim = res['qt.x3']
    x4_sim = res['qt.x4']
    t_sim = res['time']
    u1_sim = res['u1']
    u2_sim = res['u2']

    # Check simulation results for testing purposes
    assert N.abs(res.final('qt.x1') - 0.05642485) < 1e-3
    assert N.abs(res.final('qt.x2') - 0.05510478) < 1e-3
    assert N.abs(res.final('qt.x3') - 0.02736532) < 1e-3
    assert N.abs(res.final('qt.x4') - 0.02789808) < 1e-3
    assert N.abs(res.final('u1') - 6.0) < 1e-3
    assert N.abs(res.final('u2') - 5.0) < 1e-3

    # Plot simulation result
    if with_plots:
        plt.figure(1)
        plt.subplot(2, 2, 1)
        plt.plot(t_sim, x3_sim)
        plt.subplot(2, 2, 2)
        plt.plot(t_sim, x4_sim)
        plt.subplot(2, 2, 3)
        plt.plot(t_sim, x1_sim)
        plt.subplot(2, 2, 4)
        plt.plot(t_sim, x2_sim)

        plt.figure(2)
        plt.subplot(2, 1, 1)
        plt.plot(t_sim, u1_sim, 'r')
        plt.subplot(2, 1, 2)
        plt.plot(t_sim, u2_sim, 'r')

    # Load optimization problem
    op = transfer_to_casadi_interface("QuadTankPack.QuadTank_ParEstCasADi",
                                      model_path)

    # Create measurement data object for optimization
    Q = N.diag([1., 1., 10., 10.])
    data_x1 = N.vstack([t_meas, y1_meas])
    data_x2 = N.vstack([t_meas, y2_meas])
    data_u1 = N.vstack([t_meas, u1])
    data_u2 = N.vstack([t_meas, u2])
    unconstrained = OrderedDict()
    unconstrained['qt.x1'] = data_x1
    unconstrained['qt.x2'] = data_x2
    unconstrained['u1'] = data_u1
    unconstrained['u2'] = data_u2
    measurement_data = MeasurementData(Q=Q, unconstrained=unconstrained)

    # Set optimization options and optimize
    opts = op.optimize_options()
    opts['n_e'] = 60
    opts['measurement_data'] = measurement_data
    opts['init_traj'] = res.result_data
    opts['nominal_traj'] = res.result_data
    res = op.optimize(options=opts)

    # Load state profiles
    x1_opt = res["qt.x1"]
    x2_opt = res["qt.x2"]
    x3_opt = res["qt.x3"]
    x4_opt = res["qt.x4"]
    u1_opt = res["qt.u1"]
    u2_opt = res["qt.u2"]
    t_opt = res["time"]

    # Extract estimated values of parameters
    a1_opt = res.final("qt.a1")
    a2_opt = res.final("qt.a2")

    # Print and assert estimated parameter values
    print('a1: ' + str(a1_opt * 1e4) + 'cm^2')
    print('a2: ' + str(a2_opt * 1e4) + 'cm^2')
    a_ref = [0.02656702, 0.02713898]
    N.testing.assert_allclose(1e4 * N.array([a1_opt, a2_opt]),
                              [0.02656702, 0.02713898],
                              rtol=1e-4)

    # Plot estimated trajectories
    if with_plots:
        plt.figure(1)
        plt.subplot(2, 2, 1)
        plt.plot(t_opt, x3_opt, 'k')
        plt.subplot(2, 2, 2)
        plt.plot(t_opt, x4_opt, 'k')
        plt.subplot(2, 2, 3)
        plt.plot(t_opt, x1_opt, 'k')
        plt.subplot(2, 2, 4)
        plt.plot(t_opt, x2_opt, 'k')

        plt.figure(2)
        plt.subplot(2, 1, 1)
        plt.plot(t_opt, u1_opt, 'k')
        plt.subplot(2, 1, 2)
        plt.plot(t_opt, u2_opt, 'k')
        plt.show()
formatter = matplotlib.ticker.ScalarFormatter()
#~ formatter.set_powerlimits((-2,2))

problem = ["simple", "circuit", "vehicle", "double_pendulum", "ccpp",
           "dist4"][4]
source = ["Modelica", "strings"][0]
with_plots = True
with_plots = False
#~ blt = True
#~ blt = False
#~ full_blt = True

if source != "Modelica":
    raise ValueError
class_name = "CombinedCycleStartup.Startup6Reference"
file_paths = (os.path.join(get_files_path(), "CombinedCycle.mo"),
              os.path.join(get_files_path(), "CombinedCycleStartup.mop"))
opts = {'generate_html_diagnostics': True}
model_fmu = load_fmu(compile_fmu(class_name, file_paths,
                                 compiler_options=opts))
final_time = 5000.
opts = model_fmu.simulate_options()
opts['CVode_options']['rtol'] = 1e-10
opts['CVode_options']['atol'] = 1e-10
sim_res = model_fmu.simulate(final_time=final_time, options=opts)

eps = 1e-8
for i in xrange(2):
    if i == 0:
        linear_solver = "symbolicqr"
        title = "Symbolic QR"
Example #30
0
def run_demo(with_plots=True):
    """
    This example is based on the multibody mechanics double pendulum example from the Modelica Standard Library (MSL).

    The MSL example has been modified by adding a torque on the first revolute joint of the pendulum as a top-level
    input. The considered optimization problem is to invert both pendulum bodies with bounded torque.

    This example needs linear solver MA27 to work.
    """
    # Simulate system with linear state feedback to generate initial guess
    file_paths = (os.path.join(get_files_path(), "DoublePendulum.mo"),
                  os.path.join(get_files_path(), "DoublePendulum.mop"))
    comp_opts = {'inline_functions': 'all', 'dynamic_states': False,
            'expose_temp_vars_in_fmu': True, 'equation_sorting': True, 'automatic_tearing': True}
    init_fmu = load_fmu(compile_fmu("DoublePendulum.Feedback", file_paths, compiler_options=comp_opts))
    init_res = init_fmu.simulate(final_time=3., options={'CVode_options': {'rtol': 1e-10}})
    
    # Set up optimization
    op = transfer_optimization_problem('Opt', file_paths, compiler_options=comp_opts)
    opts = op.optimize_options()
    opts['IPOPT_options']['linear_solver'] = "ma27"
    opts['n_e'] = 100
    opts['init_traj'] = init_res
    opts['nominal_traj'] = init_res

    # Symbolic elimination
    op = BLTOptimizationProblem(op)

    # Solve optimization problem
    res = op.optimize(options=opts)

    # Extract solution
    time = res['time']
    phi1 = res['pendulum.revolute1.phi']
    phi2 = res['pendulum.revolute2.phi']
    u = res['u']

    # Verify solution for testing purposes
    try:
        import casadi
    except:
        pass
    else:
        cost = float(res.solver.solver_object.output(casadi.NLP_SOLVER_F))
        N.testing.assert_allclose(cost, 9.632883808252522, rtol=5e-3)

    # Plot solution
    if with_plots:
        plt.close(1)
        plt.figure(1)
        plt.subplot(2, 1, 1)
        plt.plot(time, phi1, 'b')
        plt.plot(time, phi2, 'r')
        plt.legend(['$\phi_1$', '$\phi_2$'])
        plt.ylabel('$\phi$')
        plt.xlabel('$t$')
        plt.grid()
        
        plt.subplot(2, 1, 2)
        plt.plot(time, u)
        plt.ylabel('$u$')
        plt.xlabel('$t$')
        plt.grid()
        
        plt.show()