Ejemplo n.º 1
0
    def rule_odes(m, t):
        exprs = dict()
        exprs['A'] = -m.P['k1'] * m.Z[t, 'A']
        exprs['B'] = m.P['k1'] * m.Z[t, 'A'] - m.P['k2'] * m.Z[t, 'B']
        exprs['C'] = m.P['k2'] * m.Z[t, 'B']
        exprs['D'] = -m.P['k3'] * m.Z[t, 'D']
        exprs['E'] = m.P['k3'] * m.Z[t, 'D']
        return exprs

    # As with other multiple experiments KIPET examples, we have different TemplateBuilders for
    # each of the experiments.
    builder1.set_odes_rule(rule_odes)

    # In this example, it is useful to bound the profiles to stop the components with 0 concentration,
    # i.e. D and E, from having very large absorbances.
    builder1.bound_profile(var='S', bounds=(0, 10))

    #=========================================================================
    # EXPERIMENT 2 and 3
    #=========================================================================
    builder2 = TemplateBuilder()
    components2 = {'A': 3e-3, 'B': 0, 'C': 0, 'D': 1e-3, 'E': 0}
    builder2.add_mixture_component(components2)
    builder2.add_parameter('k1', init=1.5, bounds=(0.001, 10))
    #There is also the option of providing initial values: Just add init=... as additional argument as above.
    builder2.add_parameter('k2', init=0.2, bounds=(0.0001, 1))
    builder2.add_parameter('k3', init=0.6, bounds=(0.3, 2))

    # Additionally, we do not add the spectral data to the TemplateBuilder, rather supplying the
    # TemplateBuilder before data is added as an argument into the function
    builder.add_parameter('k1', init=2.0, bounds=(1.0,5.0)) 
    #There is also the option of providing initial values: Just add init=... as additional argument as above.
    builder.add_parameter('k2',init = 0.2, bounds=(0.0,1))
    builder.add_spectral_data(D_frame)

    # define explicit system of ODEs
    def rule_odes(m,t):
        exprs = dict()
        exprs['A'] = -m.P['k1']*m.Z[t,'A']
        exprs['B'] = m.P['k1']*m.Z[t,'A']-m.P['k2']*m.Z[t,'B']
        exprs['C'] = m.P['k2']*m.Z[t,'B']
        return exprs
    
    builder.set_odes_rule(rule_odes)
    
    builder.bound_profile(var = 'S', bounds = (0,200))
    opt_model = builder.create_pyomo_model(0.0,10.0)
    
    #=========================================================================
    #USER INPUT SECTION - VARIANCE ESTIMATION 
    #=========================================================================
    # For this problem we have an input D matrix that has some noise in it
    # We can therefore use the variance estimator described in the Overview section
    # of the documentation and Section 4.3.3
    v_estimator = VarianceEstimator(opt_model)
    v_estimator.apply_discretization('dae.collocation',nfe=100,ncp=3,scheme='LAGRANGE-RADAU')
    
    # It is often requried for larger problems to give the solver some direct instructions
    # These must be given in the form of a dictionary
    options = {}
    # While this problem should solve without changing the deault options, example code is 
    # define explicit system of ODEs
    def rule_odes(m, t):
        exprs = dict()
        exprs['A'] = -m.P['k1'] * m.Z[t, 'A']
        exprs['B'] = m.P['k1'] * m.Z[t, 'A'] - m.P['k2'] * m.Z[t, 'B']
        exprs['C'] = m.P['k2'] * m.Z[t, 'B']
        return exprs

    builder.set_odes_rule(rule_odes)

    # if we know that a certain concentration or absorbance cannot be higher than a certain value
    # and we wish to constrain the variable with some bound then we can use the following approach:

    #Please note that by adding in additional bounds and constraints

    builder.bound_profile(var='S', comp='B', bounds=(0, 200))
    builder.bound_profile(var='S',
                          comp='A',
                          bounds=(50, 65),
                          profile_range=(1650, 1800))

    builder.bound_profile(var='C',
                          comp='B',
                          bounds=(0.00, 0.00022),
                          profile_range=(0, 2))

    # here the function arguments are for which profile, which component, the bounds that you wish to set
    # and finally the profile_range over which to set the bound (i.e. wavelength or time). Also not that the
    # function is called before the create_pyomo_model and also that if all component profiles should be bounded
    # we can use:
    # builder.bound_profile(var = 'S', bounds = (0,200))